ASP.NET Web API 使用Swagger
ASP.NET Web API 使用Swagger使用笔记
最近换了工作,其中Webapi这块没有文档,之前有了解过Swagger借此机会好好整理下常用的地方分享给有需要的小伙伴。
概述:
1.swagger 引用
2.swagger 问题1.action 方法名称相同处理
3.swagger 问题2.序列化出来的JSON NULL 值处理
4. 汉化及controller说明
5. 统一返回HttpResponseMessage 返回类型 指定
6. 自定义 HTTP Header (oauth2.0 请求)
7.请求示例remarks
1.swagger 引用
第一步:

第二步:修改SwaggerConfig.cs
如 api 版本号,title

第三步:创建项目XML注释文档
右键项目→属性→生成→选中下方的 "XML文档文件" 然后保存

配置启用:
c.IncludeXmlComments(string.Format("{0}/bin/BjxWebApis.XML",System.AppDomain.CurrentDomain.BaseDirectory));
第四步:启动项目
地址:http://localhost:58303/swagger

哈哈 成功了,不对这个是最终效果,下面一步一步来实现吧。
2.swagger 问题1.action 方法名称相同处理

根据错误提示 很快发现 某位大神 同样的接口名 传递了不同参数,导致了这个错误,解决方式:

c.ResolveConflictingActions(apiDescriptions => apiDescriptions.First());
问题解决了 进行下一步
3.swagger 问题2.序列化出来的JSON NULL 值处理
先上图

等了好半天 一直不出来 打开F12一看原来有错,万能的网友帮了我,原来问题出在http://localhost:58303/swagger/docs/v1这个JSON资源上面,
序列化出来的JSON,包含了为NULL的字段,导致swagger-ui-min-js出现异常。
进一步分析是因为我项目使用的newtonsoft.json这个库的配置导致,应该忽略为NULL的字段,
对应解决办法如图: settings.NullValueHandling = NullValueHandling.Ignore;

问题解决了 开心 继续...
4. 汉化及controller说明
看图:咦 怎么控制器没有说明,这个和汉化一起说吧

第一步:定义一个provider实现ISwaggerProvider接口 包含了缓存 名:SwaggerCacheProvider
代码:

1 /// <summary>
2 /// swagger显示控制器的描述
3 /// </summary>
4 public class SwaggerCacheProvider : ISwaggerProvider
5 {
6 private readonly ISwaggerProvider _swaggerProvider;
7 private static ConcurrentDictionary<string, SwaggerDocument> _cache =new ConcurrentDictionary<string, SwaggerDocument>();
8 private readonly string _xml;
9 /// <summary>
10 ///
11 /// </summary>
12 /// <param name="swaggerProvider"></param>
13 /// <param name="xml">xml文档路径</param>
14 public SwaggerCacheProvider(ISwaggerProvider swaggerProvider,string xml)
15 {
16 _swaggerProvider = swaggerProvider;
17 _xml = xml;
18 }
19
20 public SwaggerDocument GetSwagger(string rootUrl, string apiVersion)
21 {
22
23 var cacheKey = string.Format("{0}_{1}", rootUrl, apiVersion);
24 SwaggerDocument srcDoc = null;
25 //只读取一次
26 if (!_cache.TryGetValue(cacheKey, out srcDoc))
27 {
28 srcDoc = _swaggerProvider.GetSwagger(rootUrl, apiVersion);
29
30 srcDoc.vendorExtensions = new Dictionary<string, object> { { "ControllerDesc", GetControllerDesc() } };
31 _cache.TryAdd(cacheKey, srcDoc);
32 }
33 return srcDoc;
34 }
35
36 /// <summary>
37 /// 从API文档中读取控制器描述
38 /// </summary>
39 /// <returns>所有控制器描述</returns>
40 public ConcurrentDictionary<string, string> GetControllerDesc()
41 {
42 string xmlpath = _xml;
43 ConcurrentDictionary<string, string> controllerDescDict = new ConcurrentDictionary<string, string>();
44 if (File.Exists(xmlpath))
45 {
46 XmlDocument xmldoc = new XmlDocument();
47 xmldoc.Load(xmlpath);
48 string type = string.Empty, path = string.Empty, controllerName = string.Empty;
49
50 string[] arrPath;
51 int length = -1, cCount = "Controller".Length;
52 XmlNode summaryNode = null;
53 foreach (XmlNode node in xmldoc.SelectNodes("//member"))
54 {
55 type = node.Attributes["name"].Value;
56 if (type.StartsWith("T:"))
57 {
58 //控制器
59 arrPath = type.Split('.');
60 length = arrPath.Length;
61 controllerName = arrPath[length - 1];
62 if (controllerName.EndsWith("Controller"))
63 {
64 //获取控制器注释
65 summaryNode = node.SelectSingleNode("summary");
66 string key = controllerName.Remove(controllerName.Length - cCount, cCount);
67 if (summaryNode != null && !string.IsNullOrEmpty(summaryNode.InnerText) && !controllerDescDict.ContainsKey(key))
68 {
69 controllerDescDict.TryAdd(key, summaryNode.InnerText.Trim());
70 }
71 }
72 }
73 }
74 }
75 return controllerDescDict;
76 }
77 }

第二步:定义一个JS文件,做成嵌入资源,这个js文件的功能主要有两个,一个是汉化,另一个就是在界面上显示控制器的描述文字


1 'use strict';
2 window.SwaggerTranslator = {
3 _words: [],
4
5 translate: function () {
6 var $this = this;
7 $('[data-sw-translate]').each(function () {
8 $(this).html($this._tryTranslate($(this).html()));
9 $(this).val($this._tryTranslate($(this).val()));
10 $(this).attr('title', $this._tryTranslate($(this).attr('title')));
11 });
12 },
13
14 setControllerSummary: function () {
15
16 try
17 {
18 console.log($("#input_baseUrl").val());
19 $.ajax({
20 type: "get",
21 async: true,
22 url: $("#input_baseUrl").val(),
23 dataType: "json",
24 success: function (data) {
25
26 var summaryDict = data.ControllerDesc;
27 console.log(summaryDict);
28 var id, controllerName, strSummary;
29 $("#resources_container .resource").each(function (i, item) {
30 id = $(item).attr("id");
31 if (id) {
32 controllerName = id.substring(9);
33 try {
34 strSummary = summaryDict[controllerName];
35 if (strSummary) {
36 $(item).children(".heading").children(".options").first().prepend('<li class="controller-summary" style="color:green;" title="' + strSummary + '">' + strSummary + '</li>');
37 }
38 } catch (e)
39 {
40 console.log(e);
41 }
42 }
43 });
44 }
45 });
46 }catch(e)
47 {
48 console.log(e);
49 }
50 },
51 _tryTranslate: function (word) {
52 return this._words[$.trim(word)] !== undefined ? this._words[$.trim(word)] : word;
53 },
54
55 learn: function (wordsMap) {
56 this._words = wordsMap;
57 }
58 };
59
60
61 /* jshint quotmark: double */
62 window.SwaggerTranslator.learn({
63 "Warning: Deprecated": "警告:已过时",
64 "Implementation Notes": "实现备注",
65 "Response Class": "响应类",
66 "Status": "状态",
67 "Parameters": "参数",
68 "Parameter": "参数",
69 "Value": "值",
70 "Description": "描述",
71 "Parameter Type": "参数类型",
72 "Data Type": "数据类型",
73 "Response Messages": "响应消息",
74 "HTTP Status Code": "HTTP状态码",
75 "Reason": "原因",
76 "Response Model": "响应模型",
77 "Request URL": "请求URL",
78 "Response Body": "响应体",
79 "Response Code": "响应码",
80 "Response Headers": "响应头",
81 "Hide Response": "隐藏响应",
82 "Headers": "头",
83 "Try it out!": "试一下!",
84 "Show/Hide": "显示/隐藏",
85 "List Operations": "显示操作",
86 "Expand Operations": "展开操作",
87 "Raw": "原始",
88 "can't parse JSON. Raw result": "无法解析JSON. 原始结果",
89 "Model Schema": "模型架构",
90 "Model": "模型",
91 "apply": "应用",
92 "Username": "用户名",
93 "Password": "密码",
94 "Terms of service": "服务条款",
95 "Created by": "创建者",
96 "See more at": "查看更多:",
97 "Contact the developer": "联系开发者",
98 "api version": "api版本",
99 "Response Content Type": "响应Content Type",
100 "fetching resource": "正在获取资源",
101 "fetching resource list": "正在获取资源列表",
102 "Explore": "浏览",
103 "Show Swagger Petstore Example Apis": "显示 Swagger Petstore 示例 Apis",
104 "Can't read from server. It may not have the appropriate access-control-origin settings.": "无法从服务器读取。可能没有正确设置access-control-origin。",
105 "Please specify the protocol for": "请指定协议:",
106 "Can't read swagger JSON from": "无法读取swagger JSON于",
107 "Finished Loading Resource Information. Rendering Swagger UI": "已加载资源信息。正在渲染Swagger UI",
108 "Unable to read api": "无法读取api",
109 "from path": "从路径",
110 "server returned": "服务器返回"
111 });
112 $(function () {
113 window.SwaggerTranslator.translate();
114 window.SwaggerTranslator.setControllerSummary();
115 });

第三步:修改App_Start中的SwaggerConfig.cs文件,主要代码有两行
c.CustomProvider((defaultProvider) => new SwaggerCacheProvider(defaultProvider, string.Format("{0}/bin/BjxWebApis.XML", System.AppDomain.CurrentDomain.BaseDirectory)));
c.InjectJavaScript(System.Reflection.Assembly.GetExecutingAssembly(), "BjxWebApis.swagger.js");
JS资源文件命名空间是:文件所在项目的命名空间.文件径路.文件名
执行:

汉化有了 但是控制器说明没有,经过排查发现 var summaryDict = data.ControllerDesc; 没有获取到对象
使用var summaryDict = data.vendorExtensions.ControllerDesc;
再试,成功了,继续下一个目标,返回类型指定

5. 统一返回HttpResponseMessage 返回类型 指定
很多时候我们会使用HttpResponseMessage 作为返回对象 很方便,但是Swagger 不知道我们具体返回啥,它不看我们的业务代码!!
直接上干货,使用SwaggerResponse 指定返回类型,两个httpstatuscode 对应不同返回值

看下效果

是不是想马上试试,可是问题又来了 接口有用户验证,没关系,继续看下一个
6. 自定义 HTTP Header (oauth2.0 请求)
在开发API时常常需要验证权限,验证参数放在Http请求头中是再好不过了。WebAPI配合过滤器验证权限即可
首先我们需要创建一个 IOperationFilter 接口的类。IOperationFilter:
上代码:

1 /// <summary>
2 /// swagger 增加 AUTH 选项
3 /// </summary>
4 public class HttpAuthHeaderFilter : IOperationFilter
5 {
6 /// <summary>
7 /// 应用
8 /// </summary>
9 /// <param name="operation"></param>
10 /// <param name="schemaRegistry"></param>
11 /// <param name="apiDescription"></param>
12 public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription)
13
14 {
15 if (operation.parameters == null)
16 operation.parameters = new List<Parameter>();
17 var filterPipeline = apiDescription.ActionDescriptor.GetFilterPipeline(); //判断是否添加权限过滤器
18 var isAuthorized = filterPipeline.Select(filterInfo => filterInfo.Instance).Any(filter => filter is IAuthorizationFilter); //判断是否允许匿名方法
19 var allowAnonymous = apiDescription.ActionDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().Any();
20 if (isAuthorized && !allowAnonymous)
21 {
22 operation.parameters.Add(new Parameter { name = "Authorization", @in = "header", description = "安全", required = false, type = "string" });
23 }
24 }
25 }

SwaggerConfig.cs 配置中加入 c.OperationFilter<HttpAuthHeaderFilter>();

看效果 可以 开始测试吧,可问题又来了 难道要对着实体对象编一个JSON对象,不用下一个我们来做个请求示例,继续...
7.请求示例remarks
先看个效果:

要想实现这个效果 ,我们需要使用呢remarks 看写法吧,需要说明的是 <remarks>前有个空格 请求地址 空格+tab 才能出来上面效果

/// <summary>
/// 记录日志
/// </summary>
/// <remarks>
/// 日志请求示例
///
/// Post Api/Subject/Log
///
/// {
/// "subjectId":100012,
/// "mouldId":0,
/// "statType":"10",
/// "entityId":0,
/// "viewUserId":1,
/// "ip":"127.0.0.1",
/// "devId":"1111",
/// "source":1
/// }
/// </remarks>
/// <param name="model"></param>
/// <returns></returns>

总结:
规范化api的编写和注释,以及标准化文档,对于团队的开发效率有很大的提升,也有利于项目的维护。使用在线接口文档后,方便前后端工程师沟通,测试人员测试只需要在页面输入参数,点击调用就可以看到调用结果。
转自:https://www.cnblogs.com/lhbshg/p/8711604.html
ASP.NET Web API 使用Swagger的更多相关文章
- ASP.NET Web API 使用Swagger生成在线帮助测试文档,支持多个GET
以下为教程: 在现有webapi项目中,nuget安装以下两个插件 swagger.net.ui swashbuckle 安装完毕后可以卸载Swagger.NET,此处不需要! 安装完毕后屏蔽以下代码 ...
- ASP.NET Web API 使用Swagger生成在线帮助测试文档
Swagger-UI简单而一目了然.它能够纯碎的基于html+javascript实现,只要稍微整合一下便能成为方便的API在线测试工具.项目的设计架构中一直提倡使用TDD(测试驱动)原则来开发,sw ...
- ASP.NET Web API 使用Swagger使用笔记
https://www.cnblogs.com/lhbshg/p/8711604.html 最近换了工作,其中Webapi这块没有文档,之前有了解过Swagger借此机会好好整理下常用的地方分享给有需 ...
- asp.net web api 安装swagger
使用nuget控制台, 输入 Install-Package Swashbuckle,回车,等待安装引用.nuget国内没有镜像,安装比较慢 安装成功后会多出一个引用 右键工程点--属性,左边导航栏选 ...
- ASP.NET Core 中文文档 第二章 指南 (09) 使用 Swagger 生成 ASP.NET Web API 在线帮助测试文档
原文:ASP.NET Web API Help Pages using Swagger 作者:Shayne Boyer 翻译:谢炀(kiler) 翻译:许登洋(Seay) 对于开发人员来说,构建一个消 ...
- ASP.NET Web API Help Pages using Swagger
Understanding the various methods of an API can be a challenge for a developer when building a consu ...
- ASP.NET Web API 文件產生器 - 使用 Swagger
转帖:http://kevintsengtw.blogspot.hk/2015/12/aspnet-web-api-swagger.html Swagger 是一套 API 互動文件產生器,使用 HT ...
- Swagger 生成 ASP.NET Web API
使用 Swagger 生成 ASP.NET Web API 在线帮助测试文档 原文:ASP.NET Web API Help Pages using Swagger作者:Shayne Boyer翻译: ...
- ASP.NET Web API 中使用 swagger 来管理 API 文档
本文以 ASP.NET Web API 为后台框架,利用 EF6 连接 postgreSQL 数据库,使用 swagger 来生成 REST APIs文档.文章分二个部分,第一部分主要讲如何用 EF6 ...
随机推荐
- Python语言中enumerate()及zip()函数的使用例子
在Python编程语言中,enumerate()及zip()是两个常用的内置函数,这两个函数功能类似,但又有所区别,下面通过两个例子分别进行说明. enumerate()函数 该函数在字面上是枚举.列 ...
- python-opencv学习第一章
一.opencv读入图像 retval=cv2.imread(文件名[,显示控制参数]) 常用三个参数如下 CV. IMREAD_UNCHANGED 不改变原先什么样子现在就是什么样子 CV. IMR ...
- linux系统安装步骤
在虚拟机安装OEL linux 6.5图解(64位) 一,搭建虚拟机环境 虚拟机环境建议10.0版本及以上 可以从官网上下载OELlinux的安装包,http://www.oracle.com 打开虚 ...
- android sp文件一个键值保存多条信息
之前碰到过这样的问题,sp文件只能够append,或者清空.其实一个键值,通过,分割,或者替代可以实现多条信息的存储.下面是一个举例: package com.ctbri.weather.utils; ...
- webpack安装低于4版本(没有配置webpack.config.js)
webpack安装低于4版本(没有配置webpack.config.js) webpack 无需配置输出参数-o 低版本 1.初始化项目 npm init -y 初始化项目 2.安装webpack@ ...
- 二进制方式安装mysql
下载官方打包好的rpm的集合 https://downloads.mysql.com/archives/get/file/mysql-5.7.20-1.el7.x86_64.rpm-bundle.ta ...
- Mysql 创建函数出现This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA
This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its declaration and binary mys ...
- 从 sourcemap 中获取源码
使用 paazmaya/shuji: Reverse engineering JavaScript and CSS sources from sourcemaps 可以从 sourcemap 中获取源 ...
- RabbitMQ使用(下)
RabbitMQ从信息接收者角度可以看做三种模式,一对一,一对多(此一对多并不是发布订阅,而是每条信息只有一个接收者)和发布订阅.其中一对一是简单队列模式,一对多是Worker模式,而发布订阅包括发布 ...
- JavaScript —— 常见用途
javaScript 简介 第一个JavaScript 程序: 点击按钮显示日期 <!DOCTYPE html> <html> <head> <meta ...