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ƽ̨ÔÚÏß½Ó¿ÚÎĵµ");
|
//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<HiddenApiFilter>();
|
//oauth2.0
|
c.OperationFilter<HttpAuthHeaderFilter>();
|
c.ResolveConflictingActions(apiDescriptions => apiDescriptions.First());
|
|
//»ñÈ¡¿ØÖÆÆ÷µÄ×¢ÊÍ·½·¨Àà
|
c.CustomProvider((defaultProvider) => new SwaggerControllerDescProvider(defaultProvider, GetXmlCommentsPath(thisAssembly.GetName().Name)));
|
|
//swagger ·Ö×é
|
c.GroupActionsBy(apiDesc => apiDesc.GetControllerAndActionAttributes<ControllerGroupAttribute>().Any() ? apiDesc.GetControllerAndActionAttributes<ControllerGroupAttribute>().First().GroupName + "." + apiDesc.GetControllerAndActionAttributes<ControllerGroupAttribute>().First().Useage : "ÎÞÄ£¿é");
|
})
|
.EnableSwaggerUi(c =>
|
{
|
c.DocumentTitle("пµÏMESƽ̨ÔÚÏß½Ó¿ÚÎĵµ");
|
c.InjectJavaScript(thisAssembly, "VueWebApi.Scripts.swagger_lang.js");//ºº»¯js
|
});
|
}
|
/// <summary>
|
/// XML·¾¶Æ´½Ó
|
/// </summary>
|
/// <param name="name"></param>
|
/// <returns></returns>
|
protected static string GetXmlCommentsPath(string name)
|
{
|
return string.Format(@"{0}\bin\{1}.XML", AppDomain.CurrentDomain.BaseDirectory, name);
|
}
|
}
|
}
|
|
/// <summary>
|
/// ControllerÃèÊöÐÅÏ¢
|
/// </summary>
|
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
|
public class ControllerGroupAttribute : Attribute
|
{
|
/// <summary>
|
/// µ±Ç°ControllerËùÊôÄ£¿é ÇëÓÃÖÐÎÄ
|
/// </summary>
|
public string GroupName { get; private set; }
|
|
/// <summary>
|
/// µ±Ç°controllerÓÃ; ÇëÓÃÖÐÎÄ
|
/// </summary>
|
public string Useage { get; private set; }
|
|
/// <summary>
|
/// ControllerÃèÊöÐÅÏ¢ ¹¹Ôì
|
/// </summary>
|
/// <param name="groupName">Ä£¿éÃû³Æ</param>
|
/// <param name="useage">µ±Ç°controllerÓÃ;</param>
|
public ControllerGroupAttribute(string groupName, string useage)
|
{
|
if (string.IsNullOrEmpty(groupName) || string.IsNullOrEmpty(useage))
|
{
|
throw new ArgumentNullException("·Ö×éÐÅÏ¢²»ÄÜΪ¿Õ");
|
}
|
GroupName = groupName;
|
Useage = useage;
|
}
|
}
|
|
/// <summary>
|
/// Òþ²Ø½Ó¿Ú£¬²»Éú³Éµ½swaggerÎĵµÕ¹Ê¾
|
/// </summary>
|
/// <seealso cref="System.Attribute" />
|
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
|
public partial class HiddenApiAttribute : Attribute { }
|
/// <summary>
|
/// Class HiddenApiFilter.
|
/// </summary>
|
/// <seealso cref="Swashbuckle.Swagger.IDocumentFilter" />
|
public class HiddenApiFilter : IDocumentFilter
|
{
|
/// <summary>
|
/// ÖØÐ´Apply·½·¨£¬ÒƳýÒþ²Ø½Ó¿ÚµÄÉú³É
|
/// </summary>
|
/// <param name="swaggerDoc">swaggerÎĵµÎļþ</param>
|
/// <param name="schemaRegistry"></param>
|
/// <param name="apiExplorer">api½Ó¿Ú¼¯ºÏ</param>
|
public void Apply(SwaggerDocument swaggerDoc, SchemaRegistry schemaRegistry, IApiExplorer apiExplorer)
|
{
|
foreach (ApiDescription apiDescription in apiExplorer.ApiDescriptions)
|
{
|
if (Enumerable
|
.OfType<HiddenApiAttribute>(apiDescription.GetControllerAndActionAttributes<HiddenApiAttribute>())
|
.Any())
|
{
|
string key = "/" + apiDescription.RelativePath;
|
if (key.Contains("?"))
|
{
|
int idx = key.IndexOf("?", StringComparison.Ordinal);
|
key = key.Substring(0, idx);
|
}
|
|
swaggerDoc.paths.Remove(key);
|
}
|
}
|
}
|
}
|
|
/// <summary>
|
/// swagger Ôö¼Ó AUTH Ñ¡Ïî
|
/// </summary>
|
public class HttpAuthHeaderFilter : IOperationFilter
|
{
|
/// <summary>
|
/// Ó¦ÓÃ
|
/// </summary>
|
/// <param name="operation"></param>
|
/// <param name="schemaRegistry"></param>
|
/// <param name="apiDescription"></param>
|
public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription)
|
|
{
|
if (operation.parameters == null)
|
operation.parameters = new List<Parameter>();
|
var filterPipeline = apiDescription.ActionDescriptor.GetFilterPipeline(); //ÅжÏÊÇ·ñÌí¼ÓȨÏÞ¹ýÂËÆ÷
|
var isAuthorized = filterPipeline.Select(filterInfo => filterInfo.Instance).Any(filter => filter is IAuthorizationFilter); //ÅжÏÊÇ·ñÔÊÐíÄäÃû·½·¨
|
var allowAnonymous = apiDescription.ActionDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().Any();
|
if (isAuthorized && !allowAnonymous)
|
{
|
operation.parameters.Add(new Parameter { name = "Authorization", @in = "header", description = "°²È«", required = false, type = "string" });
|
}
|
}
|
}
|
|
/// <summary>
|
/// swaggerÏÔʾ¿ØÖÆÆ÷µÄÃèÊö
|
/// </summary>
|
public class SwaggerControllerDescProvider : ISwaggerProvider
|
{
|
private readonly ISwaggerProvider _swaggerProvider;
|
private static ConcurrentDictionary<string, SwaggerDocument> _cache = new ConcurrentDictionary<string, SwaggerDocument>();
|
private readonly string _xml;
|
/// <summary>
|
///
|
/// </summary>
|
/// <param name="swaggerProvider"></param>
|
/// <param name="xml">xmlÎĵµÂ·¾¶</param>
|
public SwaggerControllerDescProvider(ISwaggerProvider swaggerProvider, string xml)
|
{
|
_swaggerProvider = swaggerProvider;
|
_xml = xml;
|
}
|
|
/// <summary>
|
/// Gets the swagger.
|
/// </summary>
|
/// <param name="rootUrl">The root URL.</param>
|
/// <param name="apiVersion">The API version.</param>
|
/// <returns>SwaggerDocument.</returns>
|
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<string, object> { { "ControllerDesc", GetControllerDesc() } };
|
_cache.TryAdd(cacheKey, srcDoc);
|
}
|
return srcDoc;
|
}
|
|
/// <summary>
|
/// ´ÓAPIÎĵµÖжÁÈ¡¿ØÖÆÆ÷ÃèÊö
|
/// </summary>
|
/// <returns>ËùÓпØÖÆÆ÷ÃèÊö</returns>
|
public ConcurrentDictionary<string, string> GetControllerDesc()
|
{
|
string xmlpath = _xml;
|
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;
|
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;
|
}
|
}
|