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 }