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 接口,如下

相关推荐
optimistic_chen1 天前
【Java EE进阶 --- SpringBoot】Spring IoC
spring boot·后端·spring·java-ee·mvc·loc
wuk9981 天前
在Spring MVC中使用查询字符串与参数
java·spring·mvc
原来是好奇心2 天前
深入剖析Spring Boot中Spring MVC的请求处理流程
spring boot·spring·mvc
xkroy2 天前
创建Spring MVC和注解
学习·spring·mvc
期待のcode2 天前
SpringMVC的请求接收与结果响应
java·后端·spring·mvc
Pure03193 天前
Spring MVC BOOT 中体现的设计模式
spring·设计模式·mvc
The Sheep 20233 天前
.NetCore MVC
mvc·.netcore
YDS8293 天前
SpringMVC —— Spring集成web环境和SpringMVC快速入门
java·spring·mvc·springmvc
xkroy3 天前
Sping Web MVC入门
mvc
他们都不看好你,偏偏你最不争气3 天前
【iOS】MVC架构
前端·ios·mvc·objective-c·面向对象