本文版权归博客园和做者吴双本人共同全部,转载和爬虫请注明博客园蜗牛原文地址,cnblogs.com/tdwscss
请原谅我这个标题党,写到了第100篇随笔,说是深度优化,其实也并无什么深度。源码也没怎么修改,若是你想使用WebApi Swagger文档,请先移步到上一篇的中度优化。html
第一篇:ASP.NET WebApi 文档Swagger中度优化 http://www.cnblogs.com/tdws/p/6100126.htmlnode
第二篇:ASP.NET WebApi 文档Swashbuckle.Core与SwaggerUI深度定制git
1.文档先后端分离github
2.项目结构ajax
3.实现分Area(模块)来筛选所需展现的Controllerjson
第三篇 :ASP.NET WebApi 文档增长登陆 http://www.cnblogs.com/tdws/p/7395556.html后端
本篇文章提供源码,下载连接: https://github.com/coderws/CustomSwagger (因为博客园只能上传10MB,就放github上吧,不求star,只为了方便你们下载)api
因为Swagger原版的swagger页面和资源js css等文件被嵌入到dll当中,虽然咱们能够找到swagger UI的源码,但用起来依然感到有些不便。因此使用了github上另外一个开源项目sosoapi,它的文档功能也是基于swagger的,不过为咱们作好了必定得拓展,好比现成的中英切换一类的。而且资源彻底与以前的嵌入性资源不一样,直接分离出来一个swagger UI的文件夹,包括js,css,images,html等等,这样的话,咱们修改起来很方便呀,能够作到你想要的定制化,而且我将swagger的后台处理源码down下来,加到解决方案当中,之后遇到问题,不再用收到dll不能修改和新增功能的困扰。能够将swagger做为你框架中的一部分。app
你能够看到Swashbuckle.Core。就是Swagger的后台源码,展开Test项目,其中的Doc文件夹,就是所有的SwaggerUI的内容啦,index.html就是咱们的文档首页:
再说Area分组前提一点小的改动
Required为醒目红色
Swagger 最大宽度增长到1100px,
左侧增长模块筛选,点击筛选后,将只显示对应模块下。
具体的实现方式,就是根据你的模块名称,来筛选api访问路径
如上图第一个user,就表明user模块了,第二个user才是控制器名称。这样的定义,使用了MVC5的新特性RouteAttribute和RoutePrefixAttribute,他们用于在controller中自定义路由,你能够下载源码看到。
那咱们左侧菜单栏的数据是哪儿来的呢。请看源码SwaggerConfig中,我定义了这样一个方法:
/// <summary> /// 从API文档中读取控制器描述 /// </summary> /// <returns>全部控制器描述</returns> public static ConcurrentDictionary<string, string> GetControllerDesc(HashSet<string> moduleList) { string xmlpath = String.Format("{0}/bin/SwaggerCustom.Test.XML", AppDomain.CurrentDomain.BaseDirectory); 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")) { //模块信息 var moduleName = arrPath[length - 2]; moduleList.Add(moduleName); //获取控制器注释 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; }
原本这个方法仅用于读取Controller注释的,可是既然这里读取了xml,我也就不必再读一遍了。我增长了一个HashSet<string>类型的参数,在集合中数据每个元素的数据是惟一的,因此使用它来存模块信息,xml每次遍历到Controller的时候,我都会将其Modules信息读取出来(好比namespace SwaggerCustom.Test.Controllers.Admin.AdminRoleController ),那么倒数第二位的单词就是模块名称。这样一来咱们的模块信息也包含在了json中,看下图AreaDescription,他说明了我有三个模块。
那么接下来就是要作页面渲染前的筛选工做了。我首先猜想渲染必定和返回json中的path(接口路径)有关,因此我在swagger-ui-ext.js中搜索path,总算找到告终果:
以下所示:遍历时,经过筛选Module模块,对不符合我所想要的module进行直接return,而不向下执行,最终达到想要的目的。之因此说我没有作深度优化的缘由也是这里,真正的深度优化应该是在后台代码中所筛选,只返回本身想要的json结果,偷懒了。
因此下图,就是我点击Admin选项后所筛选的结果,该模块下只有两个Controller。
有关我我的所增长的js代码,在Doc/lib/swagger-custom.js中。
//获取Controller描述 function SwaggerCustom() { this.setControllerSummary = function () { $.ajax({ type: "get", async: true, url: $("#input_baseUrl").val(), dataType: "json", success: function (data) { var summaryDict = data.ControllerDesc; var id, controllerName, strSummary; $("#resources_container .resource").each(function (i, item) { id = $(item).attr("id"); if (id) { controllerName = id.substring(9); strSummary = summaryDict[controllerName]; if (strSummary) { $(item).children(".heading").children(".options").prepend('<li style="color:red;" class="controller-summary" title="' + strSummary + '">' + strSummary + '</li>'); } } }); swaggerCustom.loadMenu(data.AreaDescription); expendtoggle();//注册菜单收缩事件 } }); }; //获取当前参数 this.getQueryString = function (name) { var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)"); var r = window.location.search.substr(1).match(reg); if (r != null) return unescape(r[2]); return null; }, this.loadMenu = function (modules) { var url = window.location.href; url = url.substring(0, url.lastIndexOf('?')); $('body').prepend('<div class="menu-expender" id="menuExpend">←</div><div id="moduleMenu"><div onclick="menuClick(this)" data-url="' + url + '?module=all" " data-module="all" class="menu-inner" >所有</div></div>'); var menuInner = ''; modules.forEach(function (item) { menuInner += '<div onclick="menuClick(this)" data-url="' + url + '?module=' + item.toLowerCase() + '" data-module="' + item.toLowerCase() + '" class="menu-inner" >' + item + '</div>'; }); $('#moduleMenu').append(menuInner); $('#moduleMenu').css("position", "fixed").css("top", "20%"); } } var swaggerCustom = new SwaggerCustom(); var swaggerCustomGlobalData = { currentModule: "all" } $(function () { swaggerCustomGlobalData.currentModule = swaggerCustom.getQueryString('module') == null ? "all" : swaggerCustom.getQueryString('module'); //alert(swaggerCustomGlobalData.currentModule); }); var swaggerStyle = { showActionLink: function () { $("li .toggleEndpointList").css("color", "#2392f7"); }, titleStyle: function () { $("h2 .toggleEndpointList").css("color", "green"); }, showDetailLink: function () { $("li .expandResource").css('color', '#996633'); }, paramTable: function () { $('.fullwidth.parameters thead tr th:nth-child(1)').width('50px'); $('.fullwidth.parameters thead tr th:nth-child(2)').width('350px'); $('.fullwidth.parameters thead tr th:nth-child(3)').width('100px'); $('.fullwidth.parameters thead tr th:nth-child(4)').width('60px'); $('.fullwidth.parameters thead tr th:nth-child(5)').width('400px'); $('td textarea').width('380px'); }, init: function () { this.showActionLink(); this.titleStyle(); this.showDetailLink(); //this.paramTable(); } } function menuClick(ele) { window.location.href = (ele.dataset.url); } function expendtoggle() { $('#menuExpend').toggle(function () { $(this).html('→'); $('#moduleMenu').hide(); }, function () { $(this).html('←'); $('#moduleMenu').show(); }); }
使用直接copy走SwaggerConfig.cs和Doc文件放到你项目下,而且引用Swashbuckle就没问题(能够直接拿源码类库,也能够直接从nuget上安装)。而且你想使用这个模块划分的功能,就必定要符合路由规则api/modulename/controller/action.由于模块的筛选就是经过modulename嘛。若是你只想使用swagger的基本功能,看上一篇的分享就足够了。拿到本次分享的源码,你就能够在其中合理的修改源码,自定义你的功能
2017-03-13补充几点
这个处理结果的展现,经过在action的描述文档注释上 ,增长节点<response code="201">Returns the newly created item</response>
Swagger不识别ActionResult,须要肯定返回类型,因此在Core中 须要增长特性标签
依然请原谅我这个标题党。
若是个人点滴分享对你有点滴帮助,欢迎点下方红色按钮关注,我将持续输出分享。也欢迎为我,也为你本身点赞。关于本篇源码有任何问题,欢迎留言。