ASP.NET Swagger 创建与汉化生成 API说明文档

ASP.NET Swagger 创建与汉化生成 API说明文档

本篇文章将以ASP.NET Web Api 示例:

 

1.首先引入下面两个NuGet包

 

 

 

2.安装完成后App_Start文件夹下出现SwaggerConfig.cs和SwaggerNet.cs

 

 

 3.打开SwaggerNet.cs文件,注释下面的代码:

[assembly: WebActivator.PreApplicationStartMethod(typeof(WebApi.App_Start.SwaggerNet), "PreStart")]
[assembly: WebActivator.PostApplicationStartMethod(typeof(WebApi.App_Start.SwaggerNet), "PostStart")]

 

 

 4.右键项目属性,在Web选项中,启动操作勾选特定页,输入swagger/ui/index#/   当然这不是必须的

    在项目属性的生成项中勾选输出XML文档

 

 

 

 

 

 

 5.在App_Start文件夹下创建SwaggerCacheProvider.cs

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

 

6.配置SwaggerConfig.cs   //注下面代码已对Swagger默认接口做了隐藏 

 1 using System.Web.Http;
 2 using WebActivatorEx;
 3 using WebApi;
 4 using Swashbuckle.Application;
 5 using System;
 6 using Swashbuckle.Swagger;
 7 using System.Web.Http.Description;
 8 using System.Linq;
 9 using WebApi.App_Start;
10 
11 [assembly: PreApplicationStartMethod(typeof(SwaggerConfig), "Register")]
12 
13 namespace WebApi
14 {
15     /// <summary>
16     /// 配置SwaggerConfig
17     /// </summary>
18     public class SwaggerConfig
19     {
20         /// <summary>
21         /// Register
22         /// </summary>
23         public static void Register()
24         {
25             var thisAssembly = typeof(SwaggerConfig).Assembly;
26 
27             GlobalConfiguration.Configuration
28                 .EnableSwagger(c =>
29                 {
30                     c.SingleApiVersion("v1", "WebApi User Guide");
31                     c.IncludeXmlComments(GetXmlCommentsPath(GetXmlCommentsPath(thisAssembly.GetName().Name)));
32                     c.CustomProvider((defaultProvider) => new SwaggerCacheProvider(defaultProvider, string.Format(@"{0}\bin\WebApi.XML", System.AppDomain.CurrentDomain.BaseDirectory)));
33                     c.DocumentFilter<HiddenApiFilter>();//隐藏Swagger 自带API及隐藏具体Api
34                 })
35                 .EnableSwaggerUi(c =>
36                 {
37                     c.InjectJavaScript(System.Reflection.Assembly.GetExecutingAssembly(), "WebApi.scripts.swagger.js");
38                 });
39         }
40         /// <summary>
41         /// 获取接口的注释
42         /// </summary>
43         /// <param name="name"></param>
44         /// <returns></returns>
45         protected static string GetXmlCommentsPath(string name)
46         {
47             return string.Format(@"{0}\bin\WebApi.XML", AppDomain.CurrentDomain.BaseDirectory, name);
48         }
49     }
50 }
51 /// <summary>
52 /// 隐藏Swagger默认接口
53 /// </summary>
54 [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
55 public partial class HiddenApiAttribute : Attribute { }
56 /// <summary>
57 /// 隐藏Swagger默认接口
58 /// </summary>
59 public class HiddenApiFilter : IDocumentFilter
60 {
61     public void Apply(SwaggerDocument swaggerDoc, SchemaRegistry schemaRegistry, IApiExplorer apiExplorer)
62     {
63         foreach (ApiDescription apiDescription in apiExplorer.ApiDescriptions)
64         {
65             var _key = "/" + apiDescription.RelativePath.TrimEnd('/');
66             // 过滤 swagger 自带的接口
67             if (_key.Contains("/api/Swagger") && swaggerDoc.paths.ContainsKey(_key))
68                 swaggerDoc.paths.Remove(_key);
69 
70             //隐藏具体Api接口 需要在想隐藏的api 上面添加特性[HiddenApi]
71             if (Enumerable.OfType<HiddenApiAttribute>(apiDescription.GetControllerAndActionAttributes<HiddenApiAttribute>()).Any())
72             {
73                 string key = "/" + apiDescription.RelativePath;
74                 if (key.Contains("?"))
75                 {
76                     int idx = key.IndexOf("?", System.StringComparison.Ordinal);
77                     key = key.Substring(0, idx);
78                 }
79                 swaggerDoc.paths.Remove(key);
80             }
81         }
82     }
83 }

 

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

 

 8.因对swagger默认接口做了隐藏所以我们要自己写一下  //我就随便写了一下 具体需求你们自己定义

 

 

 

 9.效果如图所示:

 

swagger文档非常适用于前后端分离 

如需转载请注明出处

 

posted @ 2019-09-02 22:55  松栀南山  阅读(952)  评论(0编辑  收藏  举报