public class CachingSwaggerProvider : ISwaggerProvider { private static ConcurrentDictionary<string, SwaggerDocument> _cache = new ConcurrentDictionary<string, SwaggerDocument>(); private readonly ISwaggerProvider _swaggerProvider; public CachingSwaggerProvider(ISwaggerProvider swaggerProvider) { _swaggerProvider = swaggerProvider; } public SwaggerDocument GetSwagger(string rootUrl, string apiVersion) { , rootUrl, apiVersion); SwaggerDocument srcDoc = null; (!_cache.TryGetValue(cacheKey, out srcDoc)) { srcDoc = _swaggerProvider.GetSwagger(rootUrl, apiVersion); srcDoc.vendorExtensions = , GetControllerDesc() } }; _cache.TryAdd(cacheKey, srcDoc); } return srcDoc; } 从API文档中读取控制器描述 ConcurrentDictionary<string, string> GetControllerDesc() { , System.AppDomain.CurrentDomain.BaseDirectory); ConcurrentDictionary<string, string> controllerDescDict = new ConcurrentDictionary<string, string>(); if (File.Exists(xmlpath)) { XmlDocument xmldoc = new XmlDocument(); xmldoc.Load(xmlpath); string type = string.Empty, path = string.Empty, controllerName = string.Empty; string[] arrPath; .Length; XmlNode summaryNode = null; )) { type = node.Attributes[].Value; )) { //控制器 arrPath = type.Split(); length = arrPath.Length; controllerName = arrPath[length - 1]; )) { //获取控制器注释 summaryNode = node.SelectSingleNode(); string key = controllerName.Remove(controllerName.Length - cCount, cCount); if (summaryNode != null && !string.IsNullOrEmpty(summaryNode.InnerText) && !controllerDescDict.ContainsKey(key)) { controllerDescDict.TryAdd(key, summaryNode.InnerText.Trim()); } } } } } return controllerDescDict; } }
View Codec.CustomProvider((defaultProvider) => new CachingSwaggerProvider(defaultProvider));
上面汉化的js中的方法_setControllerSummary通过读取ControllerDesc属性设置了控制器的描述,至此项目可以无忧使用接口描述文档。
3.使用了MEF导致接口重复问题解决方案
代码请参照项目中的SwaggerConfig_解决MEF重复问题.cs文件
ApiExplorer思路拓展该篇到这里可以结束了,考虑到有的读者想了解更多Swagger的实现内幕,这里再做一下简单的思路引导。
Swagger的读取所有Controller和Action借助于IApiExplorer接口的方法GetApiExplorer,其中IApiExplorer在System.Web.Http中。