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

相关推荐
Libby博仙6 小时前
asp.net core mvc中的模板页(父页面,布局页)和部分视图(Partial View)
后端·asp.net·mvc
杂货铺的小掌柜1 天前
spring mvc源码学习笔记之七
学习·spring·mvc
杂货铺的小掌柜1 天前
spring mvc源码学习笔记之九
学习·spring·mvc
杂货铺的小掌柜1 天前
spring mvc源码学习笔记之十
学习·spring·mvc
是萝卜干呀1 天前
Backend - C# asp .net core MVC
c#·mvc·.netcore
sin22012 天前
springmvc--请求参数的绑定
java·mvc
HelloZheQ2 天前
Spring MVC 介绍与实践
java·spring·mvc
新知图书2 天前
第一个Spring MVC 6入门示例
java·spring·mvc
qq_441996052 天前
Servlet 和 Spring MVC:区别与联系
spring·servlet·mvc