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

  • 使用WPF、OwinSelfHost和Swagger创建自托管的Web API已关闭评论
  • 182 次浏览
  • A+
所属分类:.NET技术
摘要

在本篇博客中,我将介绍如何在WPF应用程序中使用OwinSelfHost和Swagger来创建自托管的Web API。我们将使用WPF作为我们的应用程序界面,OwinSelfHost来自托管我们的Web API,并使用Swagger来为我们的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>     [RoutePrefix("api")]     public class 模拟接口Controller : BaseController     {         /// <summary>         /// 同步信息         /// </summary>         /// <returns></returns>         [Route("fs_syncPayinfo")]         [HttpGet]         public IHttpActionResult SyncPayInfo()         {             string json = @"{""code"":1,""message"":""同步成功""}";             return Json(JObject.Parse(json));         } }

步骤4:配置Swagger 在解决方案资源管理器中,右键单击"Properties"文件夹,选择"添加" -> "新建文件"。命名为"Startup.cs"。在文件中添加以下代码:

其中包含了记录日志中间件等类,具体看下载的代码

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

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;  [assembly: OwinStartup(typeof(MockAPI.Startup))]  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[length - 1];                             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);         }

这里代码只有部分截图,具体下载代码查看   点击下载

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

 点击API地址打开文档界面

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

 

 

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