ASP.NET WebApi 文档Swagger中度优化
本文版权归博客园和作者吴双本人共同所有,转载和爬虫请注明原文地址:www.cnblogs.com/tdws
在后台接口开发中,接口文档是必不可少的。在复杂的业务当中和多人对接的情况下,简单的接口文档又不能满足需求,试想你的单应用后台有几十个模块,几百甚至更多的接口,又有上百个ViewModel。怎么能让人用起来更顺手更明了?本篇介绍第一步的中度优化,下一篇将分享下一阶段的深度优化。
第一篇:ASP.NET WebApi 文档Swagger中度优化
1.上手使用
2.Controller注释读取和汉化
3.Actionf group by 分组
4.通过exe整合xxxModel.xml和xxxAPI.XML
5.通过批处理命令在生成后调用exe
第二篇:ASP.NET WebApi 文档Swashbuckle.Core与SwaggerUI深度定制 http://www.cnblogs.com/tdws/p/6103289.html
第三篇 :ASP.NET WebApi 文档增加登录 http://www.cnblogs.com/tdws/p/7395556.html
Swagger是一款完全开源的文档工具,其优点在于前后端的完整分离,他们之间的契约就是Json的数据格式。其后台项目就是github中的Swashbuckle。其前台项目就是github中的SwaggerUI。有一点需要注意的是,如果你直接从nuget安装Swashbuckle的话,你也并不想做更多的定制化,那么UI界面你完全不需要处理,因为所有的资源Resources都是嵌入到Swashbuckle.dll当中的,你可以在vs对象管理器中查看到Resources,如下图,是不是又复习了dll的作用了呢?其中还可以包含css,js,image等资源:

看下本次分享的效果图吧,只选了四个Controller做展示,个人觉得还是比较明了的吧,如果模块和控制器多了起来,就会深刻体会到好处:

nuget中搜索Swashbuckle并安装到你的WebApi项目中,其他的不用安装哦。
安装完成后你的App_Start中会多一个SwaggerConfig这样一个配置文件,这个文件是Swagger为我们留下的配置入口,我们可以根据其中的注释和介绍做很多事情。然后我把Swagger单独出来一个文件夹,直接将配置类拖进去,如下效果:

下一步配置你的项目属性,在其生成选项当中,选择下图配置:

配置文件中主要有两个入口:EnableSagger和EnableSwaggerUi,顾名思义,配置其后台项和前台项。

找到下面这行代码,传入你所需的两个字符串

下一步找到IncludeXmlComments方法,配置读取XML的路径:
c.IncludeXmlComments(string.Format("{0}/bin/SwaggerDemo.XML", System.AppDomain.CurrentDomain.BaseDirectory));
至此基本就可以显示你的接口了,请访问:localhost:xxxx/swagger 你可能会问为什么我没有添加页面也能展示,这就是因为页面和其路由设置都在dll中了!下面这段源码揭示了为什么可以直接通过路由访问到你的swagger主页,当然你也可以不必关心下面这段:
public void EnableSwaggerUi(
string routeTemplate,
Action<SwaggerUiConfig> configure = null)
{
var config = new SwaggerUiConfig(_discoveryPaths, _rootUrlResolver);
if (configure != null) configure(config); _httpConfig.Routes.MapHttpRoute(
name: "swagger_ui" + routeTemplate,
routeTemplate: routeTemplate,
defaults: null,
constraints: new { assetPath = @".+" },
handler: new SwaggerUiHandler(config)
); if (routeTemplate == DefaultRouteTemplate)
{
_httpConfig.Routes.MapHttpRoute(
name: "swagger_ui_shortcut",
routeTemplate: "swagger",
defaults: null,
constraints: new { uriResolution = new HttpRouteDirectionConstraint(HttpRouteDirection.UriResolution) },
handler: new RedirectHandler(_rootUrlResolver, "swagger/ui/index"));
}
}
默认情况下,Controller注释是没有读取的。那么你需要通过如下配置来达到目的,增加这样一个类,不用问为什么。下面这段代码也是参考了一位园友的。汉化我也没必要讲了,他已经说的很详细了。
public class CachingSwaggerProvider : ISwaggerProvider
{
private static ConcurrentDictionary<string, SwaggerDocument> _cache =
new ConcurrentDictionary<string, SwaggerDocument>(); private readonly ISwaggerProvider _swaggerProvider; public CachingSwaggerProvider(ISwaggerProvider swaggerProvider)
{
_swaggerProvider = swaggerProvider;
} public SwaggerDocument GetSwagger(string rootUrl, string apiVersion)
{
var cacheKey = String.Format("{0}_{1}", rootUrl, apiVersion);
SwaggerDocument srcDoc = null;
//只读取一次
if (!_cache.TryGetValue(cacheKey, out srcDoc))
{ //AppendModelToCurrentXml();
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 static ConcurrentDictionary<string, string> GetControllerDesc()
{
string xmlpath = String.Format("{0}/bin/SwaggerDemo.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"))
{
//获取控制器注释
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;
}
}
并且在SwaggerConfig找到下面这行代码:
c.CustomProvider((defaultProvider) => new CachingSwaggerProvider(defaultProvider));
至此XML读取完成。
下面这个功能通过我们自定义的Attribute来实现。先往下看,不用问为什么,功能实现后自然明白啦:
/// <summary>
/// Controller描述信息
/// </summary>
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class ControllerGroupAttribute : Attribute
{
/// <summary>
/// 当前Controller所属模块 请用中文
/// </summary>
public string GroupName { get; private set; } /// <summary>
/// 当前controller用途 请用中文
/// </summary>
public string Useage { get; private set; } /// <summary>
/// Controller描述信息 构造
/// </summary>
/// <param name="groupName">模块名称</param>
/// <param name="useage">当前controller用途</param>
public ControllerGroupAttribute(string groupName, string useage)
{
if (string.IsNullOrEmpty(groupName) || string.IsNullOrEmpty(useage))
{
throw new ArgumentNullException("groupName||useage");
}
GroupName = groupName;
Useage = useage;
}
}
给你的每个Controller加上这个Attribute:

为了分模块,我做了这种描述,其他内容不一一描述:


在Swagger找到GroupActionsBy方法:
并且按照你所设定的分组Attribute来分组排序,最终达到我们想要的效果,请仔细阅读代码,就自然理解了:
c.GroupActionsBy(apiDesc => apiDesc.GetControllerAndActionAttributes<ControllerGroupAttribute>().Any() ?
apiDesc.GetControllerAndActionAttributes<ControllerGroupAttribute>().First().GroupName + "_" +
apiDesc.GetControllerAndActionAttributes<ControllerGroupAttribute>().First().Useage : "无模块归类");
上面的效果,你可能看不到Model层的描述信息(如果你的实体没有在其他层是会正常显示的)。但是Model分层了,怎么能展示呢,我目前给出的解决方案是合并XML.写了一个ConsoleApp,当然你也可以手动来复制处理。

通过相对路径,将model层的xml生成到与API层相同的路径下,方便我们来处理。ConsoleApp的代码如下
static void Main(string[] args)
{
AppendModelToCurrentXml();
Console.WriteLine(AppDomain.CurrentDomain.BaseDirectory);
Console.WriteLine("XML整合成功");
//Console.ReadLine();
} public static void AppendModelToCurrentXml()
{
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.Load(AppDomain.CurrentDomain.BaseDirectory + @"/bin/Model.XML");
var membersNode = xmlDocument.GetElementsByTagName("members")[]; //Model层Members节点
xmlDocument.Load(AppDomain.CurrentDomain.BaseDirectory + @"/bin/SwaggerDemo.XML");
var currentMembersNode = xmlDocument.GetElementsByTagName("members")[]; //API层Members节点
for (int i = ; i < membersNode.ChildNodes.Count; i++)
{
var memberNode = membersNode.ChildNodes[i];
currentMembersNode.AppendChild(memberNode.Clone());
if (memberNode.HasChildNodes)
{
memberNode.AppendChild(memberNode.ChildNodes[]);
}
}
xmlDocument.Save(AppDomain.CurrentDomain.BaseDirectory + @"/bin/SwaggerDemo.XML");
}
至于我为什么要取路径时选择appDomain,是因为我准备把该exe文件放置到webAPI项目的根目录下,这样取到的路径就是API项目的物理路径,如果把物理路径写死,很烦的,你懂的,因为发布或者到其他人电脑中,物理路径基本就变了。这段代码的主要功能就是把Model层中所生成的XML中的Members节点的所有内容,Copy到API项目的XML当中。

并且,为了不用每次都手动调用exe文件,我使用批处理命令,在每次项目生成后,自动执行exe.

Swagger的前后端分离,靠json格式的契约,你可以在network中查看json结果,下一篇深度定制分享将会用到它。

本篇多数是配置化的内容,只不过在实际操作的时候,面对不同情况,我们希望能得到更好的结果。动手尝试一下吧,如果有问题和不足的地方,欢迎留言探讨,万一你以后用上了呢,不,应该说WebApi文档你是一定用得上。下一篇,将会更深一步的优化,让我们拿到源码后,无论有什么特别的需求,都能自己亲手修改,而不被蒙蔽在dll中。
如果我的点滴分享对你有点滴帮助,欢迎点下方红色按钮关注,我将持续分享。也欢迎为我,也为你自己点赞。
2016.11.27补充感谢 春華秋實 的如下建议:

ASP.NET WebApi 文档Swagger中度优化的更多相关文章
- ASP.NET WebApi 文档Swagger深度优化
本文版权归博客园和作者吴双本人共同所有,转载和爬虫请注明博客园蜗牛原文地址,cnblogs.com/tdws 写在前面 请原谅我这个标题党,写到了第100篇随笔,说是深度优化,其实也并没有什么深度 ...
- WebApi 文档Swagger
NET WebApi 文档Swagger中度优化 本文版权归博客园和作者吴双本人共同所有,转载和爬虫请注明原文地址:www.cnblogs.com/tdws 写在前面 在后台接口开发中,接口文 ...
- 使用Swagger 搭建高可读性ASP.Net WebApi文档
一.前言 在最近一个商城项目中,使用WebApi搭建API项目.但开发过程中,前后端工程师对于沟通接口的使用,是非常耗时的.之前也有用过Swagger构建WebApi文档,但是API文档的可读性并不高 ...
- 使用 swagger组件给asp.net webapi文档生成
1.名词解释 Swagger 是一个规范和完整的框架,用于生成.描述.调用和可视化 RESTful 风格的 Web 服务.总体目标是使客户端和文件系统作为服务器以同样的速度来更新.文件的方法,参数和模 ...
- Webapi文档描述-swagger优化
一.前言 最近做的项目使用WebApi,采取前后端分离的方式,后台提供API接口给前端开发人员.这个过程中遇到一个问题后台开发人员怎么提供接口说明文档给前端开发人员,最初打算使用word.Xmind思 ...
- PCB DotNetCore Swagger生成WebAPI文档配置方法
在.net framework框架下可以使用WebApiTestClientWebApi生成WebAPI接口文档与方便接口测试用,而在DotnetCore却没有找到这个工具了,baidu查找一下发现有 ...
- webapi文档
webapi文档描述-swagger 最近做的项目使用mvc+webapi,采取前后端分离的方式,后台提供API接口给前端开发人员.这个过程中遇到一个问题后台开发人员怎么提供接口说明文档给前端开发人员 ...
- Taurus.MVC 2.3 开源发布:增强属性Require验证功能,自带WebAPI文档生成功能
背景: 上周,把 Taurus.MVC 在 Linux (CentOS7) 上部署任务完成后. 也不知怎么的,忽然就想给框架集成一下WebAPI文档功能,所以就动手了. 以为一天能搞完,结果,好几天过 ...
- Springboot系列(七) 集成接口文档swagger,使用,测试
Springboot 配置接口文档swagger 往期推荐 SpringBoot系列(一)idea新建Springboot项目 SpringBoot系列(二)入门知识 springBoot系列(三)配 ...
随机推荐
- iOS逆向工程之Hopper中的ARM指令
虽然前段时间ARM被日本软银收购了,但是科技是无国界的,所以呢ARM相关知识该学的学.现在看ARM指令集还是倍感亲切的,毕竟大学里开了ARM这门课,并且做了不少的实验,当时自我感觉ARM这门课学的还是 ...
- CRL快速开发框架系列教程七(使用事务)
本系列目录 CRL快速开发框架系列教程一(Code First数据表不需再关心) CRL快速开发框架系列教程二(基于Lambda表达式查询) CRL快速开发框架系列教程三(更新数据) CRL快速开发框 ...
- CSS 3学习——box-sizing和背景
box-sizing 在CSS 2中设置元素的width和height仅仅是设置了元素内容区的宽和高,元素实际的尺寸是margin + border + padding + 内容区. CSS 3(截止 ...
- Nginx反向代理,负载均衡,redis session共享,keepalived高可用
相关知识自行搜索,直接上干货... 使用的资源: nginx主服务器一台,nginx备服务器一台,使用keepalived进行宕机切换. tomcat服务器两台,由nginx进行反向代理和负载均衡,此 ...
- BPM配置故事之案例3-参与者与数据自动加载
这才过了两天,阿海又来了. 阿海:公司决定改进管理方式,以后物资申请的申请人和申请部门要写具体使用人的名字和部门了. 小明:不是要让我改回去吧? 阿海:那太麻烦了,你能不能把申请人改成选择,选好人自动 ...
- IIS8 使用FastCGI配置PHP环境支持 过程详解
平时帮朋友们配置过一些PHP环境的服务器,但是一直使用的都是Apache HTTP+PHP,今天呢,我吧IIS+PHP配置方式给大家发一下下~呵呵. 在这里,我使用的是FastCGI模块映射的方式配置 ...
- linux下使用shell 自动执行脚本文件
以下实例本人在Centos6.5 64位操作系统中使用 一.定时复制文件 a.在/usr/local/wfjb_web_back目录下创建 tomcatBack.sh文件 文件内容: #将tomcat ...
- μCos-ii学习笔记1_概述
一.μCos-ii _概述 网上关于μCosii的文章多不胜数,本人学习的过程中也参考了很多人的理解和想法,看的是卢有亮老师的<嵌入式实时操作系统-μC/OS原理与实践>(第2版),同时也 ...
- linux启动SSH及开机自动启动
本文地址 分享提纲: 1.查看是否启动 2. 设置自动启动 1.[查看是否启动] 启动SSH服务 “/etc/init.d/sshd start”.然后用netstat -antulp | grep ...
- 第10章 Shell编程(4)_流程控制
5. 流程控制 5.1 if语句 (1)格式: 格式1 格式2 多分支if if [ 条件判断式 ];then #程序 else #程序 fi if [ 条件判断式 ] then #程序 else # ...