using System.Web.Http; using WebActivatorEx; using VueWebApi; using Swashbuckle.Application; using System.Linq; using System; using Swashbuckle.Swagger; using System.Web.Http.Description; using System.Collections.Generic; using System.Web.Http.Filters; using System.Collections.Concurrent; using System.IO; using System.Xml; [assembly: PreApplicationStartMethod(typeof(SwaggerConfig), "Register")] namespace VueWebApi { public class SwaggerConfig { public static void Register() { var thisAssembly = typeof(SwaggerConfig).Assembly; GlobalConfiguration.Configuration .EnableSwagger(c => { c.SingleApiVersion("v1", "п­µÏMESƽ̨ÔÚÏß½Ó¿ÚAPI"); //c.IncludeXmlComments(string.Format("{0}/bin/VueWebApi.XML", System.AppDomain.CurrentDomain.BaseDirectory)); //ÈÃswagger¸ù¾ÝxmlÎĵµÀ´½âÎö c.IncludeXmlComments(GetXmlCommentsPath(thisAssembly.GetName().Name)); c.IncludeXmlComments(GetXmlCommentsPath("VueWebApi")); //¹ýÂË´ËÌØÐԵĽӿڲ»ÏÔʾ c.DocumentFilter(); //oauth2.0 c.OperationFilter(); c.ResolveConflictingActions(apiDescriptions => apiDescriptions.First()); //»ñÈ¡¿ØÖÆÆ÷µÄ×¢ÊÍ·½·¨Àà c.CustomProvider((defaultProvider) => new SwaggerControllerDescProvider(defaultProvider, GetXmlCommentsPath(thisAssembly.GetName().Name))); //swagger ·Ö×é c.GroupActionsBy(apiDesc => apiDesc.GetControllerAndActionAttributes().Any() ? apiDesc.GetControllerAndActionAttributes().First().GroupName + "." + apiDesc.GetControllerAndActionAttributes().First().Useage : "ÎÞÄ£¿é"); }) .EnableSwaggerUi(c => { c.DocumentTitle("п­µÏMESƽ̨ÔÚÏß½Ó¿ÚAPI"); c.InjectJavaScript(thisAssembly, "VueWebApi.Scripts.swagger_lang.js");//ºº»¯js }); } /// /// XML·¾¶Æ´½Ó /// /// /// protected static string GetXmlCommentsPath(string name) { return string.Format(@"{0}\bin\{1}.XML", AppDomain.CurrentDomain.BaseDirectory, name); } } } /// /// ControllerÃèÊöÐÅÏ¢ /// [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] public class ControllerGroupAttribute : Attribute { /// /// µ±Ç°ControllerËùÊôÄ£¿é ÇëÓÃÖÐÎÄ /// public string GroupName { get; private set; } /// /// µ±Ç°controllerÓÃ; ÇëÓÃÖÐÎÄ /// public string Useage { get; private set; } /// /// ControllerÃèÊöÐÅÏ¢ ¹¹Ôì /// /// Ä£¿éÃû³Æ /// µ±Ç°controllerÓÃ; public ControllerGroupAttribute(string groupName, string useage) { if (string.IsNullOrEmpty(groupName) || string.IsNullOrEmpty(useage)) { throw new ArgumentNullException("·Ö×éÐÅÏ¢²»ÄÜΪ¿Õ"); } GroupName = groupName; Useage = useage; } } /// /// Òþ²Ø½Ó¿Ú£¬²»Éú³Éµ½swaggerÎĵµÕ¹Ê¾ /// /// [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)] public partial class HiddenApiAttribute : Attribute { } /// /// Class HiddenApiFilter. /// /// public class HiddenApiFilter : IDocumentFilter { /// /// ÖØÐ´Apply·½·¨£¬ÒƳýÒþ²Ø½Ó¿ÚµÄÉú³É /// /// swaggerÎĵµÎļþ /// /// api½Ó¿Ú¼¯ºÏ public void Apply(SwaggerDocument swaggerDoc, SchemaRegistry schemaRegistry, IApiExplorer apiExplorer) { foreach (ApiDescription apiDescription in apiExplorer.ApiDescriptions) { if (Enumerable .OfType(apiDescription.GetControllerAndActionAttributes()) .Any()) { string key = "/" + apiDescription.RelativePath; if (key.Contains("?")) { int idx = key.IndexOf("?", StringComparison.Ordinal); key = key.Substring(0, idx); } swaggerDoc.paths.Remove(key); } } } } /// /// swagger Ôö¼Ó AUTH Ñ¡Ïî /// public class HttpAuthHeaderFilter : IOperationFilter { /// /// Ó¦Óà /// /// /// /// public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription) { if (operation.parameters == null) operation.parameters = new List(); var filterPipeline = apiDescription.ActionDescriptor.GetFilterPipeline(); //ÅжÏÊÇ·ñÌí¼ÓȨÏÞ¹ýÂËÆ÷ var isAuthorized = filterPipeline.Select(filterInfo => filterInfo.Instance).Any(filter => filter is IAuthorizationFilter); //ÅжÏÊÇ·ñÔÊÐíÄäÃû·½·¨ var allowAnonymous = apiDescription.ActionDescriptor.GetCustomAttributes().Any(); if (isAuthorized && !allowAnonymous) { operation.parameters.Add(new Parameter { name = "Authorization", @in = "header", description = "°²È«", required = false, type = "string" }); } } } /// /// swaggerÏÔʾ¿ØÖÆÆ÷µÄÃèÊö /// public class SwaggerControllerDescProvider : ISwaggerProvider { private readonly ISwaggerProvider _swaggerProvider; private static ConcurrentDictionary _cache = new ConcurrentDictionary(); private readonly string _xml; /// /// /// /// /// xmlÎĵµÂ·¾¶ public SwaggerControllerDescProvider(ISwaggerProvider swaggerProvider, string xml) { _swaggerProvider = swaggerProvider; _xml = xml; } /// /// Gets the swagger. /// /// The root URL. /// The API version. /// SwaggerDocument. public SwaggerDocument GetSwagger(string rootUrl, string apiVersion) { var cacheKey = string.Format("{0}_{1}", rootUrl, apiVersion); SwaggerDocument srcDoc = null; //Ö»¶Áȡһ´Î if (!_cache.TryGetValue(cacheKey, out srcDoc)) { srcDoc = _swaggerProvider.GetSwagger(rootUrl, apiVersion); srcDoc.vendorExtensions = new Dictionary { { "ControllerDesc", GetControllerDesc() } }; _cache.TryAdd(cacheKey, srcDoc); } return srcDoc; } /// /// ´ÓAPIÎĵµÖжÁÈ¡¿ØÖÆÆ÷ÃèÊö /// /// ËùÓпØÖÆÆ÷ÃèÊö public ConcurrentDictionary GetControllerDesc() { string xmlpath = _xml; ConcurrentDictionary controllerDescDict = new ConcurrentDictionary(); if (File.Exists(xmlpath)) { XmlDocument xmldoc = new XmlDocument(); xmldoc.Load(xmlpath); string type = string.Empty, path = string.Empty, controllerName = string.Empty; string[] arrPath; int length = -1, cCount = "Controller".Length; XmlNode summaryNode = null; foreach (XmlNode node in xmldoc.SelectNodes("//member")) { type = node.Attributes["name"].Value; if (type.StartsWith("T:")) { //¿ØÖÆÆ÷ arrPath = type.Split('.'); length = arrPath.Length; controllerName = arrPath[length - 1]; if (controllerName.EndsWith("Controller")) { //»ñÈ¡¿ØÖÆÆ÷×¢ÊÍ summaryNode = node.SelectSingleNode("summary"); 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; } }