.Net WebApi介面Swagger集成簡單使用

来源:https://www.cnblogs.com/xiongtaotao/archive/2019/05/06/10820698.html
-Advertisement-
Play Games

Swagger介紹 Swagger 是一款RESTFUL介面的、基於YAML、JSON語言的文檔線上自動生成、代碼自動生成的工具。而我最近做的項目用的是WebAPI,前後端完全分離,這時後端使用Swagger就能夠很方便簡潔的把所寫的介面以及相關註釋展示給前端人員, 從而方便雙方的溝通,提高工作效率 ...


Swagger介紹

Swagger 是一款RESTFUL介面的、基於YAML、JSON語言的文檔線上自動生成、代碼自動生成的工具。而我最近做的項目用的是WebAPI,前後端完全分離,這時後端使用Swagger就能夠很方便簡潔的把所寫的介面以及相關註釋展示給前端人員,

從而方便雙方的溝通,提高工作效率。

官網地址:https://swagger.io/

 

開始使用Swagger

1.首先創建一個空的WebApi項目

2.添加Swagger Nuget包 Swashbuckle

 

安裝完成後開始配置Swagger

第一步:輸出XML文檔文件,右鍵點擊WebAPI項目屬性,找到生成一欄,併在 輸出XML文檔文件  選項中打鉤。

 

第二步:Swagger包安裝完以後會自動在WebApi項目的App_Start文件夾下生成SwaggerConfig配置類,程式初始化時會執行此配置類的代碼。所以要在此配置你想要實現的功能。

初始內容如下圖(博主把多餘的註釋代碼都刪掉了,並做了一點修改,所以看起來簡潔一點)

 

在EnableSwagger 配置匿名方法中註冊要讀取的XML文件路徑

 

上圖中的GetXmlCommentsPath方法代碼如下:

        /// <summary>
        /// 獲取xml路徑
        /// </summary>
        /// <returns></returns>
        protected static string GetXmlCommentsPath()
        {
            return System.String.Format(@"{0}\bin\WebApiTest.xml",System.AppDomain.CurrentDomain.BaseDirectory);
        }

註冊完XML路徑以後,就要開始寫控制器描述和介面文檔緩存的代碼了

先在App_Start文件夾中新建一個CachingSwaggerProvider類,並實現ISwaggerProvider介面

代碼如下

/// <summary>
    /// 讀取API介面註釋實現類
    /// </summary>
    public class CachingSwaggerProvider : ISwaggerProvider
    {
        private static ConcurrentDictionary<string,SwaggerDocument> _cache =
           new ConcurrentDictionary<string,SwaggerDocument>();

        private readonly ISwaggerProvider _swaggerProvider;

        /// <summary>
        /// 構造
        /// </summary>
        /// <param name="swaggerProvider"></param>
        public CachingSwaggerProvider(ISwaggerProvider swaggerProvider)
        {
            _swaggerProvider = swaggerProvider;
        }

        /// <summary>
        /// 獲取文檔
        /// </summary>
        /// <param name="rootUrl"></param>
        /// <param name="apiVersion"></param>
        /// <returns></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)) {
                //AppendModelToCurrentXml();
                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\WebApiTest.xml",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 = -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;
        }
    }
View Code

下一步在EnableSwagger 配置匿名方法中註冊CachingSwaggerProvider

全部都配置好後我們來看下效果,運行項目,並打開文檔地址://swagger/ui/index

此時我們發現文檔內容雖然出來了,但控制器的描述並沒有顯示,而且文檔內容很多都是英文註釋,並不是很好理解,所以就要執行漢化操作了(註:由於控制器描述是由於通過js讀取的,所以只有漢化後才是顯示)。

漢化Swagger文檔內容

1.在當前WebAPI項目下新建名為swagger的js文件,並把下麵的代碼全部粘貼進去

'use strict';
window.SwaggerTranslator = {
    _words: [],

    translate: function () {
        var $this = this;
        $('[data-sw-translate]').each(function () {
            $(this).html($this._tryTranslate($(this).html()));
            $(this).val($this._tryTranslate($(this).val()));
            $(this).attr('title', $this._tryTranslate($(this).attr('title')));
        });
    },

    setControllerSummary: function () {

        try {
            console.log($("#input_baseUrl").val());
            $.ajax({
                type: "get",
                async: true,
                url: $("#input_baseUrl").val(),
                dataType: "json",
                success: function (data) {

                    var summaryDict = data.ControllerDesc;
                    console.log(summaryDict);
                    var id, controllerName, strSummary;
                    $("#resources_container .resource").each(function (i, item) {
                        id = $(item).attr("id");
                        if (id) {
                            controllerName = id.substring(9);
                            try {
                                strSummary = summaryDict[controllerName];
                                if (strSummary) {
                                    $(item).children(".heading").children(".options").first().prepend('<li class="controller-summary" style="color:green;" title="' + strSummary + '">' + strSummary + '</li>');
                                }
                            } catch (e) {
                                console.log(e);
                            }
                        }
                    });
                }
            });
        } catch (e) {
            console.log(e);
        }
    },
    _tryTranslate: function (word) {
        return this._words[$.trim(word)] !== undefined ? this._words[$.trim(word)] : word;
    },

    learn: function (wordsMap) {
        this._words = wordsMap;
    }
};


/* jshint quotmark: double */
window.SwaggerTranslator.learn({
    "Warning: Deprecated": "警告:已過時",
    "Implementation Notes": "實現備註",
    "Response Class": "響應類",
    "Status": "狀態",
    "Parameters": "參數",
    "Parameter": "參數",
    "Value": "",
    "Description": "描述",
    "Parameter Type": "參數類型",
    "Data Type": "數據類型",
    "Response Messages": "響應消息",
    "HTTP Status Code": "HTTP狀態碼",
    "Reason": "原因",
    "Response Model": "響應模型",
    "Request URL": "請求URL",
    "Response Body": "響應體",
    "Response Code": "響應碼",
    "Response Headers": "響應頭",
    "Hide Response": "隱藏響應",
    "Headers": "",
    "Try it out!": "試一下!",
    "Show/Hide": "顯示/隱藏",
    "List Operations": "顯示操作",
    "Expand Operations": "展開操作",
    "Raw": "原始",
    "can't parse JSON.  Raw result": "無法解析JSON. 原始結果",
    "Model Schema": "模型架構",
    "Model": "模型",
    "apply": "應用",
    "Example Value": "實例值",
    "Username": "用戶名",
    "Password": "密碼",
    "Terms of service": "服務條款",
    "Created by": "創建者",
    "See more at": "查看更多:",
    "Contact the developer": "聯繫開發者",
    "api version": "api版本",
    "Response Content Type": "響應Content Type",
    "fetching resource": "正在獲取資源",
    "fetching resource list": "正在獲取資源列表",
    "Explore": "瀏覽",
    "Show Swagger Petstore Example Apis": "顯示 Swagger Petstore 示例 Apis",
    "Can't read from server.  It may not have the appropriate access-control-origin settings.": "無法從伺服器讀取。可能沒有正確設置access-control-origin。",
    "Please specify the protocol for": "請指定協議:",
    "Can't read swagger JSON from": "無法讀取swagger JSON於",
    "Finished Loading Resource Information. Rendering Swagger UI": "已載入資源信息。正在渲染Swagger UI",
    "Unable to read api": "無法讀取api",
    "from path": "從路徑",
    "server returned": "伺服器返回"
});
$(function () {
    window.SwaggerTranslator.translate();
    window.SwaggerTranslator.setControllerSummary();
});
View Code

2.右鍵swagger.js文件打開屬性,把生成操作改為嵌入的資源,如下圖:

3.在EnableSwaggerUi配置匿名方法中註冊js

我們再來看一下效果

我們可以看到控制器的描述已經可以看到,所以得英文註釋也被漢化,文檔也方便了很多了。

 

註:博主添加的WebAPI項目並沒有引用外部項目,所以只需讀取本項目內的XML文件,如果需要展示外部項目對象的註釋,只需要在EnableSwagger 配置匿名方法中再註冊一個要讀取的外部XML文件路徑即可。

 

其實上述控制器的描述文檔我覺得並不夠直觀,所以我又自己給控制器做了分組,覺得這樣更利於管理和維護。大家也可以根據自己的喜好做選擇了。方法如下:

1.在App_Start文件夾下新建ControllerGroupAttribute特性類,並繼承Attribute,具體代碼如下:

 /// <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;
        }
    }
View Code

2.在EnableSwagger配置匿名方法中註冊Swagger分組

 

3.給控制器加ControllerGroup特性,並填寫相關描述。

 

看下最終的效果圖:

 

顯示的還是比較直觀的,哈哈!

 

另外有一點需要擴展的是,有時候可能某些介面並不想暴露出來,這也是可以實現的,方法如下:

1.在App_Start文件夾中新建HiddenApiFilter類,並繼承IDocumentFilter介面。然後新建個空的HiddenApi過濾器,並且此過濾器只可以用於方法和類,加上AttributeUsage特性即可。代碼如下:

/// <summary>
    /// 隱藏指定api介面
    /// </summary>
    [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
    public class HiddenApiAttribute : Attribute { }

    /// <summary>
    /// 介面過濾
    /// </summary>
    public class HiddenApiFilter: IDocumentFilter
    {
        /// <summary>
        /// 獲取指定顯示介面
        /// </summary>
        /// <param name="swaggerDoc"></param>
        /// <param name="schemaRegistry"></param>
        /// <param name="apiExplorer"></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);
                }
            }
        }

    }
View Code

2.在EnableSwagger配置匿名方法中註冊

 

3.把此特性直接給指定的控制器或者介面方法用即可隱藏相關信息了!

 

總結

Swagger方便簡潔,能夠很大的提高我們的工作效率,還是值得一用的。

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • /// <summary> /// 日誌處理幫助類 /// </summary> public class LogHelper { private static Queue<string> ErrorQueue = new Queue<string>(); static Action<string> ...
  • (採用微軟公司驅動) 1.打開vs點擊工具: 點擊連接到資料庫: 選擇紅線內選項,同時在右邊點擊下載(博主已下載過了,所以右側沒有下載選項) 2.安裝好後參照oracle的安裝目錄下的 tnsnames.ora文件的最後一段修改Oracle Developer Tools for Visual St ...
  • » 引用百度解釋: 語法糖(Syntactic sugar),也譯為糖衣語法,是由英國電腦科學家彼得·約翰·蘭達(Peter J. Landin)發明的一個術語,指電腦語言中添加的某種語法,這種語法對語言的功能並沒有影響,但是更方便程式員使用。通常來說使用語法糖能夠增加程式的可讀性,從而減少程式 ...
  • 客戶端向Web伺服器發送的任意一個Http請求在任何情況下都會得到一個響應,每個響應均具有一個由3位數字表示的狀態碼和相應的描述文字,不同數值的狀態碼體現了不同類型的響應狀態。W3C對響應碼狀態的範圍進行瞭如下的規範。 100~199:信息狀態碼,代表請求已被接收並需要繼續處理。 200~299:成 ...
  • 下表為多線程操作常見對象: object data = null; ThreadPool.QueueUserWorkItem((state) => { }, data); 高 獲取或設置一個布爾值,該值指示 System.Timers.Timer 是否應只引發一次 System.Timers.Tim ...
  • 該系列文章啟發自 "How to: Create a Windows Service that schedules jobs, logs and is configurable by means of dependency injection" 閱讀優秀的項目源碼,是非常值得推崇的學習方式。閱讀之後 ...
  • Abp翻譯文檔:https://github.com/ABPFrameWorkGroup/AbpDocument2Chinese ABP官網:https://aspnetboilerplate.com https://aspnetboilerplate.com/Pages/Documents/Dyn ...
  • 其實,和swagger版本管理類似;只是平時介面太多;不好供前端人員進行篩選。 下麵進入主題: 首先: 然後設置UI: 最後就是使用啦: 在controller或者action上打上 GroupName根據自己的命名進行分組就可以了. 總的來說和設置apiVersion類似,這裡就不多介紹了 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...