卓二号 发表于 2023-6-1 18:09:13

使用WPF、OwinSelfHost和Swagger创建自托管的Web API

在本篇博客中,我将介绍如何在WPF应用程序中使用OwinSelfHost和Swagger来创建自托管的Web API。我们将使用WPF作为我们的应用程序界面,OwinSelfHost来自托管我们的Web API,并使用Swagger来为我们的API生成文档。
首先,确保你的计算机上已安装了以下组件:

[*]Visual Studio2017
[*].NET Framework(至少需要4.5版本)
接下来,按照以下步骤进行操作:
步骤1:创建新的WPF项目 在Visual Studio中创建一个新的WPF项目。命名它为"SwaggerBlog"。
步骤2:安装必要的NuGet包 在解决方案资源管理器中,右键单击项目名称,选择"管理NuGet程序包"。然后,按照以下步骤安装所需的包:

[*]Microsoft.AspNet.WebApi.OwinSelfHost
[*]Microsoft.Owin.Cors
[*]Swashbuckle
[*].。。。。
步骤3:创建API控制器 在解决方案资源管理器中,右键单击"Controllers"文件夹,选择"添加" -> "类"。命名为"模拟接口Controller.cs"。在类中添加以下代码:
using Newtonsoft.Json.Linq;
using System.Threading.Tasks;
using System.Web.Http;

namespace MockAPI.Controllers
{
    /// <summary>
    /// 模拟接口
    /// </summary>
   
    public class 模拟接口Controller : BaseController
    {
      /// <summary>
      /// 同步信息
      /// </summary>
      /// <returns></returns>
      
      
      public IHttpActionResult SyncPayInfo()
      {
            string json = @"{""code"":1,""message"":""同步成功""}";
            return Json(JObject.Parse(json));
      }
}步骤4:配置Swagger 在解决方案资源管理器中,右键单击"Properties"文件夹,选择"添加" -> "新建文件"。命名为"Startup.cs"。在文件中添加以下代码:
其中包含了记录日志中间件等类,具体看下载的代码
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Web.Http;
using System.Web.Http.Filters;
using System.Xml;
using Microsoft.Owin;
using Microsoft.Owin.Cors;
using MockAPI.Common;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using Owin;
using Swashbuckle.Application;
using Swashbuckle.Swagger;



namespace MockAPI
{
    public class Startup
    {
      public void Configuration(IAppBuilder app)
      {
            HttpConfiguration config = new HttpConfiguration();

            JsonSerializerSettings setting = new JsonSerializerSettings()
            {
                //日期类型默认格式化处理
                DateFormatHandling = DateFormatHandling.MicrosoftDateFormat,
                DateFormatString = "yyyy-MM-dd HH:mm:ss",
                //驼峰样式
                ContractResolver = new CamelCasePropertyNamesContractResolver(),
                //空值处理
                //NullValueHandling = NullValueHandling.Ignore,
                //设置序列化的最大层数
                MaxDepth = 10,
                //解决json序列化时的循环引用问题
                ReferenceLoopHandling = ReferenceLoopHandling.Ignore
            };
            config.Formatters.JsonFormatter.SerializerSettings = setting;
            config.Formatters.Remove(config.Formatters.XmlFormatter);

            config.Filters.Add(new HandlerErrorAttribute());
            //config.Routes.MapHttpRoute(
            //    name: "DefaultApi",
            //    routeTemplate: "api/{controller}/{action}/{id}",
            //    defaults: new
            //    {
            //      id = RouteParameter.Optional
            //    }
            //);
            ConfigureSwagger(config);
            //添加路由路径
            config.MapHttpAttributeRoutes();
            app.UseCors(CorsOptions.AllowAll);

            app.Use<LoggingMiddleware>();
            app.UseWebApi(config);

      }
      private static void ConfigureSwagger(HttpConfiguration config)
      {
            var thisAssembly = typeof(Startup).Assembly;
            config.EnableSwagger(c =>
             {
               c.SingleApiVersion("v1", "MockAPI");

                  //设置接口描述xml路径地址
                  var webApiXmlPath = string.Format(string.Format("{0}/MockAPI.xml", AppDomain.CurrentDomain.BaseDirectory));

               c.IncludeXmlComments(webApiXmlPath);
               c.UseFullTypeNameInSchemaIds();
                  //加入控制器描述
                  c.CustomProvider((defaultProvider) => new SwaggerControllerDescProvider(defaultProvider, webApiXmlPath));
             })
             .EnableSwaggerUi(c =>
             {
               c.DocumentTitle("MockAPI");
               c.InjectJavaScript(thisAssembly, "MockAPI.Common.Swagger.js");
             });
      }

      public class HandlerErrorAttribute : ExceptionFilterAttribute
      {
            /// <summary>
            /// 控制器方法中出现异常,会调用该方法捕获异常
            /// </summary>
            /// <param name="context">提供使用</param>
            public override void OnException(HttpActionExecutedContext context)
            {
                base.OnException(context);
                LogFile.WriteError(context.Exception.Message);
                throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.OK)
                {
                  Content = new StringContent(
                   JsonConvert.SerializeObject(
                  new
                  {
                        code = -1,
                        data = "xxx",
                        msg = context.Exception.Message
                  }), Encoding.UTF8, "text/json")
                });
            }
      };

      public class SwaggerControllerDescProvider : ISwaggerProvider
      {
            private readonly ISwaggerProvider _swaggerProvider;
            private static ConcurrentDictionary<string, SwaggerDocument> _cache = new ConcurrentDictionary<string, SwaggerDocument>();
            private readonly string _xml;
            /// <summary>
            ///
            /// </summary>
            /// <param name="swaggerProvider"></param>
            /// <param name="xml">xml文档路径</param>
            public SwaggerControllerDescProvider(ISwaggerProvider swaggerProvider, string xml)
            {
                _swaggerProvider = swaggerProvider;
                _xml = xml;
            }

            public SwaggerDocument GetSwagger(string rootUrl, string apiVersion)
            {

                var cacheKey = string.Format("{0}_{1}", rootUrl, apiVersion);
                SwaggerDocument srcDoc = null;
                //只读取一次
                if (!_cache.TryGetValue(cacheKey, out srcDoc))
                {
                  srcDoc = _swaggerProvider.GetSwagger(rootUrl, apiVersion);

                  srcDoc.vendorExtensions = new Dictionary<string, object> { { "ControllerDesc", GetControllerDesc() } };
                  _cache.TryAdd(cacheKey, srcDoc);
                }
                return srcDoc;
            }

            /// <summary>
            /// 从API文档中读取控制器描述
            /// </summary>
            /// <returns>所有控制器描述</returns>
            public ConcurrentDictionary<string, string> GetControllerDesc()
            {
                string xmlpath = _xml;
                ConcurrentDictionary<string, string> controllerDescDict = new ConcurrentDictionary<string, string>();
                if (File.Exists(xmlpath))
                {
                  XmlDocument xmldoc = new XmlDocument();
                  xmldoc.Load(xmlpath);
                  string type = string.Empty, path = string.Empty, controllerName = string.Empty;

                  string[] arrPath;
                  int length = -1, cCount = "Controller".Length;
                  XmlNode summaryNode = null;
                  foreach (XmlNode node in xmldoc.SelectNodes("//member"))
                  {
                        type = node.Attributes["name"].Value;
                        if (type.StartsWith("T:"))
                        {
                            //控制器
                            arrPath = type.Split('.');
                            length = arrPath.Length;
                            controllerName = arrPath;
                            if (controllerName.EndsWith("Controller"))
                            {
                              //获取控制器注释
                              summaryNode = node.SelectSingleNode("summary");
                              string key = controllerName.Remove(controllerName.Length - cCount, cCount);
                              if (summaryNode != null && !string.IsNullOrEmpty(summaryNode.InnerText) && !controllerDescDict.ContainsKey(key))
                              {
                                    controllerDescDict.TryAdd(key, summaryNode.InnerText.Trim());
                              }
                            }
                        }
                  }
                }
                return controllerDescDict;
            }
      }
    }
}View Code步骤5:配置OwinSelfHost 启动等等 
private void Window_Loaded(object sender, RoutedEventArgs e)
      {
            setMin();
            wsl = this.WindowState;
            this.Hide();//启动后直接最小化
            this.ResizeMode = ResizeMode.CanMinimize;
            this.txtDevice.Text = DeviceNo;
            this.txtDevice.IsReadOnly = true;

            var registry = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true);//检索指定的子项
            if (registry != null)
            {
                object a = registry.GetValue(Path.GetFileName(System.Windows.Forms.Application.ExecutablePath));
                if (a != null) this.cboAuto.IsChecked = true;
                registry.Close();
            }
            this.cboAuto.Checked += BtnClickTurnOn;
            this.cboAuto.Unchecked += BtnClickTurnOff;

            StartOptions options = new StartOptions();
            options.Urls.Add("http://+:8033");
            // 启动 OWIN host
            _disposable = WebApp.Start<Startup>(options);
      }这里代码只有部分截图,具体下载代码查看   点击下载

 点击API地址打开文档界面

 
 
至此,我们已成功创建了一个使用WPF、OwinSelfHost和Swagger的自托管Web API。你可以根据自己的需求进一步扩展和定制这个应用程序。

来源:https://www.cnblogs.com/xxxin/archive/2023/06/01/17449038.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!
页: [1]
查看完整版本: 使用WPF、OwinSelfHost和Swagger创建自托管的Web API