C#使用MVC框架创建WebApi服务接口

第一步,使用VS2019新建MVC-Web API应用程序

创建BridgeApi

第二步,运行将生成默认的示例网页,网页Url为

https://localhost:44361/home/index

右键 项目 添加 WebAPI控制器类

添加

我们可以看到App_Start目录下 有三个文件:

BundleConfig.cs代表 捆绑文件的引用

有脚本文件ScriptBundle的引用(javascript文件,后缀名.js)

和层叠样式表文件StyleBundle(即css网页排版文件,后缀名.css)

FilterConfig.cs代表全局筛选器

RouteConfig.cs代表url路由模式和action信息

右键,项目,将类库项目更新为控制台应用程序,并添加类Program

添加开源框架Topshelf的引用,添加Owin框架的引用

Topshelf 框架

Topshelf 是一个开源的跨平台的宿主服务框架,支持 Windows 和 Mono,只需要几行代码就可以构建一个很方便使用的服务宿主。

使用 Topshelf 可以非常方便的将一个 C# 控制台程序部署成为一个 Windows Service, 使用它可以很方便的构建跨平台服务寄主,而在调试时直接以控制台的形式运行即可,非常方便。

Owin框架

OWIN 允许 Web 应用从 Web 服务器分离。 它定义了在管道中使用中间件来处理请求和相关响应的标准方法。 WebAPI应用程序和中间件可以与基于 OWIN 的应用程序、服务器和中间件进行互操作。

我们在web.config(有些是app.config)增加webAPI地址和端口

ApiAddress和ApiPort

XML 复制代码
<?xml version="1.0" encoding="utf-8"?>
<!--
  有关如何配置 ASP.NET 应用程序的详细信息,请访问
  https://go.microsoft.com/fwlink/?LinkId=301880
  -->
<configuration>
  <appSettings>
    <add key="webpages:Version" value="3.0.0.0" />
    <add key="webpages:Enabled" value="false" />
    <add key="ClientValidationEnabled" value="true" />
    <add key="UnobtrusiveJavaScriptEnabled" value="true" />
	  <add key="ApiAddress" value="" />
	  <add key="ApiPort" value="45678" />
  </appSettings>
</configuration>

Program.cs如下:

cs 复制代码
using Microsoft.Owin.Hosting;
using Owin;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
using System.Web.Http;
using Topshelf;
using Topshelf.HostConfigurators;
/*
* Topshelf 是一个开源的跨平台的宿主服务框架,支持 Windows 和 Mono,只需要几行代码就可以构建一个很方便使用的服务宿主。
* 使用 Topshelf 可以非常方便的将一个 C# 控制台程序部署成为一个 Windows Service, 使用它可以很方便的构建跨平台服务寄主,
* 而在调试时直接以控制台的形式运行即可,非常方便。
* Owin框架
* OWIN 允许 Web 应用从 Web 服务器分离。 它定义了在管道中使用中间件来处理请求和相关响应的标准方法。 
* WebAPI应用程序和中间件可以与基于 OWIN 的应用程序、服务器和中间件进行互操作。
*/

namespace BridgeApi
{
    public class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("WebAPI程序启动开始...");
            HostFactory.Run(new Action<HostConfigurator>(HostConf));
            Console.ReadLine();
        }

        public static void HostConf(HostConfigurator hostConfigurator)
        {
            // 服务使用NETWORK_SERVICE内置帐户运行。身份标识,有好几种方式,如:x.RunAs("username", "password");  x.RunAsPrompt(); x.RunAsNetworkService(); 等
            hostConfigurator.RunAsLocalService();//以服务
            //x.StartAutomatically();//StartModeExtensions
            //x.StartManually();//手动模式

            hostConfigurator.SetDescription("WebAPIServer 斯内科 Topshelf Host服务的描述"); //安装服务后,服务的描述
            hostConfigurator.SetDisplayName("WebAPIServerSnake"); //显示名称
            hostConfigurator.SetServiceName("WebAPIServerSnake"); //服务名称
            Type t = hostConfigurator.GetType();//Topshelf.HostConfigurators.HostConfiguratorImpl
            Console.WriteLine(t.ToString());

            hostConfigurator.Service<TownCrier>(s =>
            {
                s.ConstructUsing(name => new TownCrier());     //配置一个完全定制的服务,对Topshelf没有依赖关系。常用的方式。
                                                               //the start and stop methods for the service
                s.WhenStarted(tc => tc.Start());              //4
                s.WhenStopped(tc => tc.Stop());
            });
        }        
    }

    public class TownCrier
    {
        public TownCrier()
        {
        }
        public void Start()
        {
            Task.Factory.StartNew(() =>
            {
                bool IsStarted = false;
                while (!IsStarted)
                {
                    try
                    {

                        string log = "服务启动成功。";
                        string urlKey = "ApiAddress";
                        string portKey = "ApiPort";
                        if (!ConfigurationManager.AppSettings.AllKeys.Contains(urlKey))
                        {
                            log = $"服务启动出现异常:App.config文件中不存在配置[{urlKey}]";
                            Console.WriteLine(log);
                            return;
                        }
                        if (!ConfigurationManager.AppSettings.AllKeys.Contains(portKey))
                        {
                            log = $"服务启动出现异常:App.config文件中不存在配置[{portKey}]";
                            Console.WriteLine(log);
                            return;
                        }
                        string apiUrl = ConfigurationManager.AppSettings[urlKey].ToString();
                        string apiPort = ConfigurationManager.AppSettings[portKey].ToString();
                        bool rtn = int.TryParse(apiPort, out int port);
                        if (!rtn)
                        {
                            log = $"服务启动出现异常:App.config文件中配置[{portKey}]值错误";
                            Console.WriteLine(log);
                            return;
                        }
                        StartOptions options = new StartOptions();
                        //options.Urls.Add($"http://localhost:{apiPort}");
                        options.Urls.Add($"http://127.0.0.1:{apiPort}");
                        //options.Urls.Add($"http://{Environment.MachineName}:{apiPort}");
                        if (!string.IsNullOrEmpty(apiUrl))
                        {
                            options.Urls.Add($"http://{apiUrl}:{apiPort}");
                        }
                        else
                        {
                            #region //自动绑定所有IP
                            string hostName = Dns.GetHostName();
                            IPAddress[] iPAddresses = Dns.GetHostAddresses(hostName);
                            foreach (IPAddress ipAddress in iPAddresses)
                            {
                                //IPv4
                                if (ipAddress.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
                                {
                                    options.Urls.Add($"http://{ipAddress}:{apiPort}");
                                }
                            }
                            #endregion
                        }
                        
                        string urls = new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(options.Urls);
                        log = $"开始启动服务,服务地址:{urls}";
                        Console.WriteLine(log);

                        //OWIN 托管服务器问题:StartOptions WebApp.Start TargetInvocationException
                        // Start OWIN host ,启动一个webapi程序
                        //  public static IDisposable Start(string url, Action<IAppBuilder> startup);

                        WebApp.Start(options, startup: Configuration);
                        Console.WriteLine($"服务启动成功。");
                        IsStarted = true;
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine($"服务启动出现异常:{ex.Message}");
                        Thread.Sleep(2000);
                    }
                }
            });
        }
        public void Stop()
        {
            Console.WriteLine($"WebApi服务退出");
        }

        public void Configuration(IAppBuilder appBuilder)
        {
            // Configure Web API for self-host. 
            HttpConfiguration config = new HttpConfiguration();
            config.MapHttpAttributeRoutes();
            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "{controller}/{action}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );
            appBuilder.UseWebApi(config);
        }
    }
}

控制器类BridgeController如下:

cs 复制代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;

namespace BridgeApi
{
    [RoutePrefix("Bridge")]
    public class BridgeController : ApiController
    {
        /// <summary>
        /// 测试API端口,假设传入一个json字符串{"TestName":"斯内科"}
        /// 请求路由Url不区分大小写
        /// http://127.0.0.1:45678/Bridge/testApi
        /// </summary>
        /// <param name="json"></param>
        /// <returns></returns>
        [Route("TestApi")]
        [HttpPost]
        public HttpResponseMessage TestApi(object objText) 
        {
            try
            {
                Microsoft.Owin.OwinContext context = ((Microsoft.Owin.OwinContext)Request.Properties["MS_OwinContext"]);
                string RemoteClient = context.Request.RemoteIpAddress + ":" + context.Request.RemotePort;
                if (objText == null)
                {
                    string returnDataNG = Newtonsoft.Json.JsonConvert.SerializeObject(new ResponseContent()
                    {
                        Code = 12345,
                        Message = $"解析失败,请求参数为空,源文本【{objText}】"
                    });
                    return new HttpResponseMessage()
                    {
                        Content = new StringContent(returnDataNG, System.Text.Encoding.UTF8, mediaType: "application/json")
                    };
                }
                string json = objText.ToString();
                TestClass testClass = Newtonsoft.Json.JsonConvert.DeserializeObject<TestClass>(json);
                if (testClass == null || string.IsNullOrEmpty(testClass.TestName))
                {
                    string returnDataNG = Newtonsoft.Json.JsonConvert.SerializeObject(new ResponseContent()
                    {
                        Code = 12345,
                        Message = $"解析失败,TestName为空,源json【{json}】"
                    });
                    return new HttpResponseMessage()
                    {
                        Content = new StringContent(returnDataNG, System.Text.Encoding.UTF8, mediaType: "application/json")
                    };
                }
                string returnData = Newtonsoft.Json.JsonConvert.SerializeObject(new ResponseContent()
                {
                    Code = 0,
                    Message = "",
                    Data = $"接收到【{RemoteClient}】上抛数据【{json}】,已处理OK,返回一个随机数【{new Random().Next(1, 100)}】"
                });
                return new HttpResponseMessage()
                {
                    Content = new StringContent(returnData, System.Text.Encoding.UTF8, mediaType: "application/json")
                };
            }
            catch (Exception ex) 
            {
                string returnDataNG = Newtonsoft.Json.JsonConvert.SerializeObject(new ResponseContent()
                {
                    Code = -1,
                    Message = $"处理时出现错误【{ex.Message}】"
                });
                return new HttpResponseMessage()
                {
                    Content = new StringContent(returnDataNG, System.Text.Encoding.UTF8, mediaType: "application/json"),
                    StatusCode = HttpStatusCode.BadRequest
                };
            }
        }
    }

    public class TestClass
    {
        public string TestName { get; set; }
    }

    /// <summary>
    /// 接口反馈的响应内容对象
    /// </summary>
    public class ResponseContent 
    {
        /// <summary>
        /// 错误号,code为0代表OK
        /// </summary>
        public int Code { get; set; }
        /// <summary>
        /// 错误描述,Code为0,这里显示空
        /// </summary>
        public string Message { get; set; }
        /// <summary>
        /// 相关数据信息,该Data可以是数组、键值对字典、字符串等任意类型数据
        /// </summary>
        public object Data { get; set; }
    }
}

运行,将其按照服务进行

使用PostMan测试WebApi 接口,如下

相关推荐
Lyyaoo.1 天前
Spring MVC 与三层架构
spring·架构·mvc
xiaodaidai丶2 天前
解决Sa-Token在 Spring MVC + WebFlux 混合架构中流式接口报错SaTokenContext 上下文尚未初始化的问题
spring·架构·mvc
xiaodaidai丶2 天前
Spring Web MVC的异步请求解读
spring boot·spring·mvc
Thomas.Sir2 天前
SpringMVC 工作原理深入解析
spring·设计模式·mvc·spring mvc
毅炼3 天前
JVM常见问题总结(2)
java·jvm·mvc
Lyyaoo.3 天前
Spring MVC中用于处理HTTP请求的常用注解
spring·http·mvc
刀法如飞15 天前
一款Go语言Gin框架MVC脚手架,满足大部分场景
go·mvc·gin
莫寒清16 天前
Spring MVC:@PathVariable 注解详解
java·spring·mvc
莫寒清19 天前
Spring MVC:@RequestParam 注解详解
java·spring·mvc