本文版权归博客园和作者吴双本人共同所有,转载和爬虫请注明博客园蜗牛原文地址,cnblogs.com/tdws

  写在前面

请原谅我这个标题党,写到了第100篇随笔,说是深度优化,其实也并没有什么深度。源码也没怎么修改,如果你想使用WebApi Swagger文档,请先移步到上一篇的中度优化。

第一篇:ASP.NET WebApi 文档Swagger中度优化 http://www.cnblogs.com/tdws/p/6100126.html

第二篇:ASP.NET WebApi 文档Swashbuckle.Core与SwaggerUI深度定制

1.文档前后端分离

2.项目结构

3.实现分Area(模块)来筛选所需展示的Controller

第三篇  :ASP.NET WebApi 文档增加登录 http://www.cnblogs.com/tdws/p/7395556.html

  文档前后端分离

本篇文章提供源码,下载链接:  https://github.com/coderws/CustomSwagger  (由于博客园只能上传10MB,就放github上吧,不求star,只为了方便大家下载)

由于Swagger原版的swagger页面和资源js css等文件被嵌入到dll当中,虽然我们可以找到swagger UI的源码,但用起来依然感到有些不便。所以使用了github上另一个开源项目sosoapi,它的文档功能也是基于swagger的,不过为我们做好了一定得拓展,比如现成的中英切换一类的。并且资源完全与之前的嵌入性资源不同,直接分离出来一个swagger UI的文件夹,包括js,css,images,html等等,这样的话,我们修改起来很方便呀,可以做到你想要的定制化,并且我将swagger的后台处理源码down下来,加到解决方案当中,以后遇到问题,再也不用收到dll不能修改和新增功能的困扰。可以将swagger作为你框架中的一部分。

  项目结构

你可以看到Swashbuckle.Core。就是Swagger的后台源码,展开Test项目,其中的Doc文件夹,就是全部的SwaggerUI的内容啦,index.html就是我们的文档首页:

  实现分Area(模块)来筛选所需展示的Controller

再说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 = -, 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 - ];
if (controllerName.EndsWith("Controller"))
{
//模块信息
var moduleName = arrPath[length - ];
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中 需要增加特性标签

依然请原谅我这个标题党。

如果我的点滴分享对你有点滴帮助,欢迎点下方红色按钮关注,我将持续输出分享。也欢迎为我,也为你自己点赞。关于本篇源码有任何问题,欢迎留言。

ASP.NET WebApi 文档Swagger深度优化的更多相关文章

  1. ASP.NET WebApi 文档Swagger中度优化

    本文版权归博客园和作者吴双本人共同所有,转载和爬虫请注明原文地址:www.cnblogs.com/tdws   写在前面 在后台接口开发中,接口文档是必不可少的.在复杂的业务当中和多人对接的情况下,简 ...

  2. WebApi 文档Swagger

    NET WebApi 文档Swagger中度优化   本文版权归博客园和作者吴双本人共同所有,转载和爬虫请注明原文地址:www.cnblogs.com/tdws   写在前面 在后台接口开发中,接口文 ...

  3. 使用Swagger 搭建高可读性ASP.Net WebApi文档

    一.前言 在最近一个商城项目中,使用WebApi搭建API项目.但开发过程中,前后端工程师对于沟通接口的使用,是非常耗时的.之前也有用过Swagger构建WebApi文档,但是API文档的可读性并不高 ...

  4. 使用 swagger组件给asp.net webapi文档生成

    1.名词解释 Swagger 是一个规范和完整的框架,用于生成.描述.调用和可视化 RESTful 风格的 Web 服务.总体目标是使客户端和文件系统作为服务器以同样的速度来更新.文件的方法,参数和模 ...

  5. Webapi文档描述-swagger优化

    一.前言 最近做的项目使用WebApi,采取前后端分离的方式,后台提供API接口给前端开发人员.这个过程中遇到一个问题后台开发人员怎么提供接口说明文档给前端开发人员,最初打算使用word.Xmind思 ...

  6. PCB DotNetCore Swagger生成WebAPI文档配置方法

    在.net framework框架下可以使用WebApiTestClientWebApi生成WebAPI接口文档与方便接口测试用,而在DotnetCore却没有找到这个工具了,baidu查找一下发现有 ...

  7. webapi文档

    webapi文档描述-swagger 最近做的项目使用mvc+webapi,采取前后端分离的方式,后台提供API接口给前端开发人员.这个过程中遇到一个问题后台开发人员怎么提供接口说明文档给前端开发人员 ...

  8. Taurus.MVC 2.3 开源发布:增强属性Require验证功能,自带WebAPI文档生成功能

    背景: 上周,把 Taurus.MVC 在 Linux (CentOS7) 上部署任务完成后. 也不知怎么的,忽然就想给框架集成一下WebAPI文档功能,所以就动手了. 以为一天能搞完,结果,好几天过 ...

  9. Springboot系列(七) 集成接口文档swagger,使用,测试

    Springboot 配置接口文档swagger 往期推荐 SpringBoot系列(一)idea新建Springboot项目 SpringBoot系列(二)入门知识 springBoot系列(三)配 ...

随机推荐

  1. MySQL中interactive_timeout和wait_timeout的区别

    在用mysql客户端对数据库进行操作时,打开终端窗口,如果一段时间没有操作,再次操作时,常常会报如下错误: ERROR (HY000): Lost connection to MySQL server ...

  2. 搭建属于自己的VIP积分系统(1)

    很久没写博客了,如果有写得不好的地方,还请多多见谅. 架构设计 需求分析 这篇文章主要是介绍此VIP系统的基础架构.说实在的,我其实对 架构方面也不是很懂,我这套框架 还是拿别人的东西改过来的,并不是 ...

  3. Java类访问权限修饰符

    一.概要 通过了解Java4种修饰符访问权限,能够进一步完善程序类,合理规划权限的范围,这样才能减少漏洞.提高安全性.具备表达力便于使用. 二.权限表 修饰符 同一个类 同一个包 不同包的子类 不同包 ...

  4. 如何区别数据库删除语句drop与delete与truncate?

    1.delete:删除数据表中的行(可以删除某一行,也可以在不删除数据表的情况下删除所有行) 删除某一行:delete from 数据表名称 where 列名称=值: 删除所有行:delete*fro ...

  5. sqlserver批量修改首字母为大写

    'hello world'  ---->   'Hello world' update tableName set columnName=CHAR(ASCII(SUBSTRING(columnN ...

  6. Linux命令【第二篇】

    1.如何过滤出已知当前目录下oldboy中的所有一级目录(提示:不包含oldboy目录下面目录的子目录及隐藏目录,即只能是一级目录). ^:以什么开头,例如^olboy表示以oldboy开头. ls: ...

  7. Zephyr OS 简介

    最新发布的开源 Zephyr Project™(Zephyr 项目)是一款小型且可伸缩的实时操作系统,尤其适用于资源受限的系统,可支持多种架构:该系统高度开源,对于开发人员社区完全开放,开发人员可根据 ...

  8. 什么是英特尔® Edison 模块?

    英特尔® Edison 模块 是一种 SD 卡大小的微型计算芯片,专为构建物联网 (IoT) 和可穿戴计算产品而设计. Edison 模块内含一个高速的双核处理单元.集成 Wi-Fi*.蓝牙* 低能耗 ...

  9. what's deviceone

    DeviceOne技术介绍 一.     DeviceOne是什么 DeviceOne(以下简称Do)是一个移动开发的平台或技术,与之对等的是Android移动开发技术,iOS移动开发技术,Windo ...

  10. Go语言实战 - revel框架教程之CSRF(跨站请求伪造)保护

    CSRF是什么?请看这篇博文“浅谈CSRF攻击方式”,说的非常清楚. 现在做网站敢不防CSRF的我猜只有两种情况,一是没什么人访问,二是局域网应用.山坡网之前属于第一种情况,哈哈,所以至今没什么问题. ...