使用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"。在文件中添加以下代码:
其中包含了记录日志中间件等类,具体看下载的代码
https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gifhttps://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gifusing 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);
}这里代码只有部分截图,具体下载代码查看 点击下载
https://img2023.cnblogs.com/blog/748637/202306/748637-20230601145531840-858739820.png
点击API地址打开文档界面
https://img2023.cnblogs.com/blog/748637/202306/748637-20230601145618806-1776755535.png
至此,我们已成功创建了一个使用WPF、OwinSelfHost和Swagger的自托管Web API。你可以根据自己的需求进一步扩展和定制这个应用程序。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
页:
[1]