代码:
swagger ui在我们的.NET CORE和.NET Framework中的展现形式是不一样的,如果有了解的,在.NET CORE中的是比.NET Framework好的。两张图对比下
.NET Framework中自带的就是这个,样式一般
.NET CORE中:
一对比core中的明显好看,本篇教你怎么在Framework 环境中搭建下面的样式,先看看效果,下面就是在Framework 环境搭建的效果:
环境:Owin
owin了解:
注:怎么搭建的可以百度一下Owin,这边主要是介绍要注意的几点,源码在github上。
①下载我们的Swagger ui
地址:
下载dist文件夹的东西
添加到我们的项目中,文件夹为swagger
② nuget Swashbuckle.Core
在App_Start中创建一个DocConfig 类,进行文档配置
using Sealee.Util;using Swashbuckle.Application;using Swashbuckle.Swagger;using System;using System.Collections.Concurrent;using System.Collections.Generic;using System.IO;using System.Linq;using System.Reflection;using System.Web;using System.Web.Http;using System.Web.Http.Description;using System.Xml;using WebApiOwin.App_Start;namespace WebApiOwin{ public class DocConfig { public static void Register(HttpConfiguration config) { Assembly _thisAssembly = typeof(DocConfig).Assembly; string _project = MethodBase.GetCurrentMethod().DeclaringType.Namespace;//项目命名空间 //注释 我们的post提交都会创建Dto来申明,这边添加了注释,前台页面就会显示 string path = System.AppDomain.CurrentDomain.BaseDirectory; string _xmlPath = string.Format("{0}/bin/{1}.XML", path, _project); string path2 = path.GetSlnPath(2); string _xmlPath2 = Path.Combine(path2, "My.Entity\\bin\\My.Entity.xml"); config.EnableSwagger(c => { c.MultipleApiVersions( (apiDesc, targetApiVersion) => { //控制器描述 IEnumerableversions = apiDesc.ActionDescriptor.ControllerDescriptor.GetCustomAttributes ().Select(x => x.Version); return versions.Any(v => $"{v.ToString()}" == targetApiVersion); }, (vc) => { //MyVersionAttribute 标识了这个属性的都需要在这里加上 这边会配合index.html页面完成 vc.Version("Token", ""); vc.Version("JwtUser", ""); }); //c.SingleApiVersion("Token", "Super duper API"); //忽略标记为已删除的属性 c.IgnoreObsoleteProperties(); //多文档描述 //文档描述 c.IncludeXmlComments(_xmlPath); //文档描述 c.IncludeXmlComments(_xmlPath2); c.ResolveConflictingActions(apiDescriptions => apiDescriptions.First()); c.CustomProvider((defaultProvider) => { //获取描述 return new MySwaggerProvider(defaultProvider, _xmlPath); }); //操作过滤 c.OperationFilter (); }); //.EnableSwaggerUi() 重点:这边我们不需要他生成页面,使用我们刚刚下载dist中的页面 } } /// /// 设置SwaggerDocument 显示的数据 /// public class MySwaggerProvider : ISwaggerProvider { private static ConcurrentDictionary_cache = new ConcurrentDictionary (); private readonly ISwaggerProvider _swaggerProvider; private readonly string _xmlPath; public MySwaggerProvider(ISwaggerProvider swaggerProvider, string xmlPath) { _swaggerProvider = swaggerProvider; _xmlPath = xmlPath; } public SwaggerDocument GetSwagger(string rootUrl, string apiVersion) { string cacheKey = string.Format("{0}_{1}", rootUrl, apiVersion); //只读取一次 if (!_cache.TryGetValue(cacheKey, out SwaggerDocument srcDoc)) { srcDoc = _swaggerProvider.GetSwagger(rootUrl, apiVersion); ConcurrentDictionary pairs = GetControllerDesc(apiVersion); //控制器描述 IList tagList = new List (); foreach (KeyValuePair item in pairs) { Tag tag = new Tag(); tag.name = item.Key; tag.description = item.Value; tagList.Add(tag); } srcDoc.tags = tagList; srcDoc.vendorExtensions = new Dictionary { { "ControllerDesc", pairs } }; _cache.TryAdd(cacheKey, srcDoc); } return srcDoc; } /// /// 从API文档中读取控制器描述 /// private ConcurrentDictionaryGetControllerDesc(string apiVersion) { ConcurrentDictionary controllerDescDict = new ConcurrentDictionary (); 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:")) { string[] typeName = type.Split(':'); Type t = Type.GetType(typeName[1]); //控制器 arrPath = type.Split('.'); length = arrPath.Length; controllerName = arrPath[length - 1]; if (controllerName.EndsWith("Controller")) { //如果分组了 if (t.GetCustomAttributes ().Count() != 0) { string version = t.GetCustomAttribute ().Version; //上面tag和下面的需要同步过滤 if (version == apiVersion) { //获取控制器注释 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; } } public class HttpHeadFilter : IOperationFilter { public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription) { // if (operation.parameters == null) // operation.parameters = new List (); ////判断是否添加授权过滤器 // var filterPipeline = apiDescription.ActionDescriptor.GetFilterPipeline(); // var isAuthorized = filterPipeline.Select(fileInfo => fileInfo.Instance).Any(filter => filter is IAuthorizationFilter); // var allowAnonymous = apiDescription.ActionDescriptor.GetCustomAttributes ().Any(); // if (isAuthorized&&!allowAnonymous) // { // operation.parameters.Add(new Parameter { name = "Authorization", @in = "head", description = "token", required = false, type = "string" }); // } if (operation == null) { return; } if (operation.parameters == null) { operation.parameters = new List (); } if (operation.security == null) { operation.security = new List >>(); } Parameter parameter = new Parameter { description = "The authorization token", @in = "header", name = "Authorization", required = true, type = "string" }; //var parameter = new Parameter //{ // description = "The authorization token", // @in = "header", // name = "Authorization", // required = true, // type = "string" //}; //显示锁标识 if (apiDescription.ActionDescriptor.GetCustomAttributes ().Any()) { //parameter.required = false; } else { Dictionary > oAuthRequirements = new Dictionary > { { "Authorization", new List () } }; operation.security.Add(oAuthRequirements); } // operation.parameters.Add(parameter); } }}
MyVersionAttribute 类用来显示我们的版本
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true)] public class MyVersionAttribute : Attribute { public MyVersionAttribute(string _version) { this.Version = _version; } ////// 版本 /// public string Version { get; set; } }
最后在我们的owin中添加DocConfig
接口列子:
③修改我们的Index.html页面
文档配置:
附授权,页面上左边的按钮:
地址:
得到这两个js,应用到你的项目
这边就是这两个js生成了授权按钮,以及样式,文本,然后把你授权需要的信息传到后台进行获取token。看下这个js你就知道了,这边不详细介绍了.应为项目中的授权不一样这边的代码你也进行相应的修改才行,别直接Copy用。
授权:一般我们的在接口中授权了的需要你携带token信息才能访问。
总结:最主要的还是不要使用代码生成的页面,需要我们的自己添加的页面,然后进行配置就好了。