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

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

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

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

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

7.请求示例remarks

先看个效果:

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

  1. /// <summary>
  2. /// 记录日志
  3. /// </summary>
  4. /// <remarks>
  5. /// 日志请求示例
  6. ///
  7. /// Post Api/Subject/Log
  8. ///
  9. /// {
  10. /// "subjectId":100012,
  11. /// "mouldId":0,
  12. /// "statType":"10",
  13. /// "entityId":0,
  14. /// "viewUserId":1,
  15. /// "ip":"127.0.0.1",
  16. /// "devId":"1111",
  17. /// "source":1
  18. /// }
  19. /// </remarks>
  20. /// <param name="model"></param>
  21. /// <returns></returns>

总结:

规范化api的编写和注释,以及标准化文档,对于团队的开发效率有很大的提升,也有利于项目的维护。使用在线接口文档后,方便前后端工程师沟通,测试人员测试只需要在页面输入参数,点击调用就可以看到调用结果。

转自:https://www.cnblogs.com/lhbshg/p/8711604.html

ASP.NET Web API 使用Swagger的更多相关文章

  1. ASP.NET Web API 使用Swagger生成在线帮助测试文档,支持多个GET

    以下为教程: 在现有webapi项目中,nuget安装以下两个插件 swagger.net.ui swashbuckle 安装完毕后可以卸载Swagger.NET,此处不需要! 安装完毕后屏蔽以下代码 ...

  2. ASP.NET Web API 使用Swagger生成在线帮助测试文档

    Swagger-UI简单而一目了然.它能够纯碎的基于html+javascript实现,只要稍微整合一下便能成为方便的API在线测试工具.项目的设计架构中一直提倡使用TDD(测试驱动)原则来开发,sw ...

  3. ASP.NET Web API 使用Swagger使用笔记

    https://www.cnblogs.com/lhbshg/p/8711604.html 最近换了工作,其中Webapi这块没有文档,之前有了解过Swagger借此机会好好整理下常用的地方分享给有需 ...

  4. asp.net web api 安装swagger

    使用nuget控制台, 输入 Install-Package Swashbuckle,回车,等待安装引用.nuget国内没有镜像,安装比较慢 安装成功后会多出一个引用 右键工程点--属性,左边导航栏选 ...

  5. ASP.NET Core 中文文档 第二章 指南 (09) 使用 Swagger 生成 ASP.NET Web API 在线帮助测试文档

    原文:ASP.NET Web API Help Pages using Swagger 作者:Shayne Boyer 翻译:谢炀(kiler) 翻译:许登洋(Seay) 对于开发人员来说,构建一个消 ...

  6. 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 ...

  7. ASP.NET Web API 文件產生器 - 使用 Swagger

    转帖:http://kevintsengtw.blogspot.hk/2015/12/aspnet-web-api-swagger.html Swagger 是一套 API 互動文件產生器,使用 HT ...

  8. Swagger 生成 ASP.NET Web API

    使用 Swagger 生成 ASP.NET Web API 在线帮助测试文档 原文:ASP.NET Web API Help Pages using Swagger作者:Shayne Boyer翻译: ...

  9. ASP.NET Web API 中使用 swagger 来管理 API 文档

    本文以 ASP.NET Web API 为后台框架,利用 EF6 连接 postgreSQL 数据库,使用 swagger 来生成 REST APIs文档.文章分二个部分,第一部分主要讲如何用 EF6 ...

随机推荐

  1. linux系统安装步骤

    在虚拟机安装OEL linux 6.5图解(64位) 一,搭建虚拟机环境 虚拟机环境建议10.0版本及以上 可以从官网上下载OELlinux的安装包,http://www.oracle.com 打开虚 ...

  2. Flume的断点续传解决

    根据需求,首先定义以下3大要素 采集源,即source——监控文件内容更新 :  exec  ‘tail -F file’ 下沉目标,即sink——HDFS文件系统  :  hdfs sink Sou ...

  3. react v16.12 源码阅读环境搭建

    搭建后的代码(Keep updated): https://github.com/lirongfei123/read-react 欢迎将源码阅读遇到的问题提到issue 环境搭建思路: 搭建一个web ...

  4. 复选框checked 选中后不显示打钩

    复选框checked 选中后不显示打钩 checkbox属性checked="checked"已有,但复选框却不显示打钩的原因   复选框绑定了click事件,点一次选中,再点击取 ...

  5. 4、Shiro之IniRealm以及用户登录认证,角色认证,权限认证

    1.我们在项目test文件夹下面新建resourse文件夹并将她设置为资源文件夹: 2.在resourse文件夹下面新建user.ini文件 user.ini文件里面声明一个用户: 先写一个用户标签[ ...

  6. java hashset输出

    for (Map.Entry<String, String> me : id_label_map.entrySet()) { System.out.println(me.getKey() ...

  7. 电商企业如何做好EDM营销随感

    对于中小型电商企业来说,运用EDM营销是一种非常不错的营销方式,正如我在电商EDM数据营销中的关键介绍一样.下面博主给大家介绍一下电商企业如何做好EDM营销. 一.在EDM邮件内容中跟客户建立信任的关 ...

  8. 【mysql】错误代码1308 Invalid use of NULL value

    错误原因是: 在最初设计表script_run_detail表时,resut_id忘记勾选不是null选项, 导致存储数据后发现result_id有NULL值,而实际上,我不希望这个字段可以存储NUL ...

  9. HTM基础之HTML标签

    HTML(超文本标记语言) html代码实际上就是一套能够被浏览器所识别的规则代码,由一个个标签组成.html代码就是一大长串字符串,而这种字符串的格式正好能够被浏览器所识别,也就有了我们的WEB页面 ...

  10. C++拷贝构造函数心得

    C++Primer作者提到拷贝构造函数调用的三种时机: 1. 当用一个类对象去初始化另外一个类对象(类似于 AClass aInstance = bInstance),这里不是调用赋值构造函数(也叫赋 ...