【PS:原文手打,轉載說明出處,部落格園

關於為什麼用Swagger

  目前稍微有點規模的公司,已經從原先的瀑布流開發到了敏捷開發,實現前後端分離,為此後端工程師只關注寫好Api即可,那程式設計師最討厭的就是寫Api文件了,故而產生了Swagger。

Swagger原理

  Swagger就是利用反射技術遍歷所有Api介面,並且從xml檔案中讀取註釋,在利用Swagger內建的模板組合html顯示至客戶端實現介面視覺化,並且可呼叫。

Asp.net WebApi Swagger整合

  1:vs2017,新建web專案,選擇WebApi

  2:刪除Views、Scripts、Models、fonts、Content、Areas目錄

  3:刪除RouteConfig.cs、FilterConfig.cs、BundleConfig.cs

  4:刪除HomeController.cs

  5:Global.asax中刪除異常程式碼

  6:nuget搜尋Swagger,安裝 Swashbuckle

  7:右鍵專案——》屬性——》生成——》輸出——》勾選XML文件檔案——》儲存

  8:修改SwaggerConfig.cs

    新增方法,釋放c.IncludeXmlComments(GetXmlCommentsPath());的註釋(注意:例如返回值為物件,然後又不在同一個專案,則需要多次呼叫)

private static string GetXmlCommentsPath()
{
return System.String.Format(@"{0}\bin\{專案名稱}.XML",
System.AppDomain.CurrentDomain.BaseDirectory);
}

  9:然後在url地址中:例如:http://localhost:port/swagger即可

Swagger進階

  1:當有dto專案時,此時dto也需要把註釋打到客戶端,注意dto專案也參考上面第7點生成xml檔案,複製第8點的方法

  2:Swagger新增Header資訊,在上方註釋的地方加入:c.OperationFilter<HttpHeaderFilter>(); 拷貝下方程式碼

public class HttpHeaderFilter : IOperationFilter
{
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 ErpFilterAttribute); //判斷是否允許匿名方法
//var allowAnonymous = apiDescription.ActionDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().Any();
if (isAuthorized)
{ operation.parameters.Add(new Parameter
{
name = "AppId",
@in = "header",
description = "應用ID(機構編號)",
required = false,
type = "string"
}); operation.parameters.Add(new Parameter
{
name = "Version",
@in = "header",
description = "版本號",
required = false,
type = "string"
}); operation.parameters.Add(new Parameter
{
name = "Ts",
@in = "header",
description = "時間戳",
required = false,
type = "string"
}); operation.parameters.Add(new Parameter
{
name = "Lang",
@in = "header",
description = "語言包",
required = false,
type = "string"
}); operation.parameters.Add(new Parameter
{
name = "Sign",
@in = "header",
description = "簽名",
required = false,
type = "string"
}); return;
}
}
}

  3:註釋的用法

  註釋的用法,在API介面中"///"三斜槓註釋的summary為介面名註釋,summary下回車<remarks>為備註,注意每個欄位的註釋必須要全面,否則無法顯示完全

  參考程式碼如下

/// <summary>
/// 角色 分頁列表
/// </summary>
/// <remarks>
/// Code返回值說明:
///
/// 錯誤碼地址:http://xxxx.com/
///
/// </remarks>
/// <param name="conditionModel">分頁查詢條件</param>
/// <returns></returns>
[HttpGet, Route("api/ClientRoles")]
public OutputModel<PagingOutputModel<List<BaseRoleDto>>> GetRoleList([FromUri]PagingInputModel conditionModel)
{
return null; }

  4:顯示控制器註釋

    新建:CachingSwaggerProvider.cs,程式碼如下 注意Mike.Merchant.WebApi.XML需要替換成你本地的工程目錄

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Xml;
using Swashbuckle.Swagger;
using System.IO; namespace Mike.Merchant.WebApi
{
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)
{
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 static ConcurrentDictionary<string, string> GetControllerDesc()
{
string xmlpath = string.Format("{0}/bin/Mike.Merchant.WebApi.XML", 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;
int length = -, 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 - ];
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;
}
}
}

    新建:swagger_show.js,程式碼如下

var ControllerSummary = function () {
var urlval = $("#input_baseUrl").val()
$.ajax({
type: "get",
async: true,
url: urlval,
dataType: "json",
success: function (data) {
var summaryDict = data.ControllerDesc;
var id, controllerName, strSummary;
$("#resources_container .resource").each(function (i, item) {
id = $(item).attr("id");
if (id) {
controllerName = id.substring();
strSummary = summaryDict[controllerName];
if (strSummary) {
$(item).children(".heading").children(".options").prepend('<li style="color:red;" class="controller-summary" title="' + strSummary + '">' + strSummary + '</li>');
}
}
});
}
});
}
ControllerSummary()

    開啟SwaggerConfig.cs 程式碼如下

    注意程式碼:c.InjectJavaScript(thisAssembly, "Mike.Merchant.WebApi.Scripts.swagger_show.js");

    後面的這個為工程目錄.資料夾.js。

GlobalConfiguration.Configuration
.EnableSwagger(c =>
{
c.SingleApiVersion("v1", "Api文件");
c.OperationFilter<HttpHeaderFilter>();
c.IncludeXmlComments(GetXmlCommentsPath());
//c.IncludeXmlComments(GetDtoXmlCommentsPath());
c.CustomProvider((defaultProvider) => new CachingSwaggerProvider(defaultProvider));
})
.EnableSwaggerUi(c =>
{
c.DocumentTitle("Api文件");
c.InjectJavaScript(thisAssembly, "Mike.Merchant.WebApi.Scripts.swagger_show.js");
});

圖片展示