MVC项目集成swagger

1、创建WebAPI项目解决方案
2、使用nuget引入Swashbuckle包

引入Swashbuckle包后App_Start文件夹下会多出一个SwaggerConfig文件

3、添加接口注释

项目属性->生成,勾选生成xml文档文件(有些太古老的WebSite项目不支持注释功能,因为根本没有生成xml这一个选项)

生成xml文档后在SwaggerConfig文件里加入配置

 var xmlAPI = $@"{AppDomain.CurrentDomain.BaseDirectory}\bin\WebApplication.xml";

 

包含xml注释,在.EnableSwagger里找到c.IncludeXmlComments并传入刚才添加的xml路径,此处是(XMLAPI)

.EnableSwagger(c=>{
  c.IncludeXmlComments(xmlAPI);
})

在Global.asax文件中注册

 

到此已经可以运行项目并且可以看到注释,在浏览器地址栏输入http://xxx/Swagger回车即可

4、汉化

  4.1创建js文件,把下面的js代码放入到项目里

  1 /// <summary>
  2 /// 中文转换
  3 ///</summary>
  4 var SwaggerTranslator = (function () {
  5     //定时执行检测是否转换成中文,最多执行500次  即500*50/1000=25s
  6     var iexcute = 0,
  7     //中文语言包
  8     _words = {
  9         "Warning: Deprecated": "警告:已过时",
 10         "Implementation Notes": "实现备注",
 11         "Response Class": "响应类",
 12         "Status": "状态",
 13         "Parameters": "参数",
 14         "Parameter": "参数",
 15         "Value": "",
 16         "Description": "描述",
 17         "Parameter Type": "参数类型",
 18         "Data Type": "数据类型",
 19         "Response Messages": "响应消息",
 20         "HTTP Status Code": "HTTP状态码",
 21         "Reason": "原因",
 22         "Response Model": "响应模型",
 23         "Request URL": "请求URL",
 24         "Response Body": "响应体",
 25         "Response Code": "响应码",
 26         "Response Headers": "响应头",
 27         "Hide Response": "隐藏响应",
 28         "Headers": "",
 29         "Try it out!": "试一下!",
 30         "Show/Hide": "显示/隐藏",
 31         "List Operations": "显示操作",
 32         "Expand Operations": "展开操作",
 33         "Raw": "原始",
 34         "can't parse JSON.  Raw result": "无法解析JSON. 原始结果",
 35         "Model Schema": "模型架构",
 36         "Model": "模型",
 37         "apply": "应用",
 38         "Username": "用户名",
 39         "Password": "密码",
 40         "Terms of service": "服务条款",
 41         "Created by": "创建者",
 42         "See more at": "查看更多:",
 43         "Contact the developer": "联系开发者",
 44         "api version": "api版本",
 45         "Response Content Type": "响应Content Type",
 46         "fetching resource": "正在获取资源",
 47         "fetching resource list": "正在获取资源列表",
 48         "Explore": "浏览",
 49         "Show Swagger Petstore Example Apis": "显示 Swagger Petstore 示例 Apis",
 50         "Can't read from server.  It may not have the appropriate access-control-origin settings.": "无法从服务器读取。可能没有正确设置access-control-origin。",
 51         "Please specify the protocol for": "请指定协议:",
 52         "Can't read swagger JSON from": "无法读取swagger JSON于",
 53         "Finished Loading Resource Information. Rendering Swagger UI": "已加载资源信息。正在渲染Swagger UI",
 54         "Unable to read api": "无法读取api",
 55         "from path": "从路径",
 56         "Click to set as parameter value": "点击设置参数",
 57         "server returned": "服务器返回"
 58     },
 59 
 60     //定时执行转换
 61      _translator2Cn = function () {
 62          if ($("#resources_container .resource").length > 0) {
 63              _tryTranslate();
 64          }
 65 
 66          if ($("#explore").text() == "Explore" && iexcute < 500) {
 67              iexcute++;
 68              setTimeout(_translator2Cn, 50);
 69          }
 70      },
 71 
 72      //设置控制器注释
 73      _setControllerSummary = function () {
 74          $.ajax({
 75              type: "get",
 76              async: true,
 77              url: $("#input_baseUrl").val(),
 78              dataType: "json",
 79              success: function (data) {
 80                  var summaryDict = data.ControllerDesc;
 81                  var id, controllerName, strSummary;
 82                  $("#resources_container .resource").each(function (i, item) {
 83                      id = $(item).attr("id");
 84                      if (id) {
 85                          controllerName = id.substring(9);
 86                          strSummary = summaryDict[controllerName];
 87                          if (strSummary) {                            
 88                              $(item).children(".heading").children(".options").prepend('<li class="controller-summary" title="' + strSummary + '">' + strSummary + '</li>');
 89                          }
 90                      }
 91                  });
 92              }
 93          });
 94      },
 95 
 96      //尝试将英文转换成中文
 97     _tryTranslate = function () {
 98         $('[data-sw-translate]').each(function () {
 99             $(this).html(_getLangDesc($(this).html()));
100             $(this).val(_getLangDesc($(this).val()));
101             $(this).attr('title', _getLangDesc($(this).attr('title')));
102         });
103     },
104     _getLangDesc = function (word) {
105         return _words[$.trim(word)] !== undefined ? _words[$.trim(word)] : word;
106     };
107 
108     return {
109         Translator: function () {
110             document.title = "API描述文档";
111             $('body').append('<style type="text/css">.controller-summary{color:#10a54a !important;word-break:keep-all;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:250px;text-align:right;cursor:default;} </style>');
112             $("#logo").html("接口描述").attr("href", "/Home/Index");
113             //设置控制器描述
114             _setControllerSummary();
115             _translator2Cn();         
116         }
117     }
118 })();
119 //执行转换
120 SwaggerTranslator.Translator();

右击刚才创建的js文件,选择属性,生成操作改为嵌入的资源

 

 

 

SwaggerConfig文件里加入配置

1  .EnableSwaggerUi(c =>{
2  //路径规则,项目命名空间.文件夹名称.js文件名称
3   c.InjectJavaScript(thisAssembly, "WebApplication.Scripts.swagger-ui-zh-cn.js");
4 })

4.2、控制器描述和接口文档缓存

 在App_Start目录下创建类文件CachingSwaggerProvider

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

SwaggerConfig文件里加入配置

 1 .EnableSwagger(c=>{ 2   c.CustomProvider((defaultProvider) => new CachingSwaggerProvider(defaultProvider,xmlAPI)); 3 }) 

 

 

 

 4.3、action 方法名称相同处理

 1 .EnableSwagger(c=>{ 2   c.ResolveConflictingActions(apiDescriptions => apiDescriptions.First()); 3 }) 

5、一个Controller不支持多个Get/Post请求问题,修改WebApiConfig.cs

打开 App_Start目录下的WebApiConfig文件

 1  public static class WebApiConfig
 2     {
 3         public static void Register(HttpConfiguration config)
 4         {
 5             // Web API 配置和服务
 6 
 7             // Web API 路由
 8             config.MapHttpAttributeRoutes();
 9 
10             config.Routes.MapHttpRoute(
11                 name: "DefaultApi",
12                 routeTemplate: "api/{controller}/{action}/{id}",
13                 defaults: new { id = RouteParameter.Optional }
14             );
15 
16             var json = config.Formatters.JsonFormatter;
17             json.SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Local;
18             json.SerializerSettings.DateFormatString = "yyyy'-'MM'-'dd' 'HH':'mm':'ss";
19         }
20     }

 

posted @ 2020-08-14 13:55  春夏秋冬的千山万水  阅读(437)  评论(0)    收藏  举报