ASP.NET WebApi 文檔Swagger深度最佳化

來源:互聯網
上載者:User

標籤:搜尋   asp   協助   文章   modules   size   cape   getc   處理   

本文著作權歸部落格園和作者吳雙本人共同所有,轉載和爬蟲請註明部落格園蝸牛原文地址,cnblogs.com/tdws

  寫在前面

請原諒我這個標題黨,寫到了第100篇隨筆,說是深度最佳化,其實也並沒有什麼深度。源碼也沒怎麼修改,如果你想使用WebApi Swagger文檔,請先移步到上一篇的中度最佳化。

 第一篇:ASP.NET WebApi 文檔Swagger中度最佳化 http://www.cnblogs.com/tdws/p/6100126.html

 第二篇:ASP.NET WebApi 文檔Swashbuckle.Core與SwaggerUI深度定製

1.文檔前後端分離

2.項目結構

3.實現分Area(模組)來篩選所需展示的Controller

 

  文檔前後端分離

本篇文章提供源碼,下載連結:  https://github.com/coderws/CustomSwagger  (由於部落格園只能上傳10MB,就放github上吧,不求star,只為了方便大家下載)

   由於Swagger原版的swagger頁面和資源js css等檔案被嵌入到dll當中,雖然我們可以找到swagger UI的源碼,但用起來依然感到有些不便。所以使用了github上另一個開源項目sosoapi,它的文檔功能也是基於swagger的,不過為我們做好了一定得拓展,比如現成的中英切換一類的。並且資源完全與之前的嵌入性資源不同,直接分離出來一個swagger UI的檔案夾,包括js,css,images,html等等,這樣的話,我們修改起來很方便呀,可以做到你想要的定製化,並且我將swagger的幕後處理源碼down下來,加到解決方案當中,以後遇到問題,再也不用收到dll不能修改和新增功能的困擾。可以將swagger作為你架構中的一部分。

  項目結構

你可以看到Swashbuckle.Core。就是Swagger的後台源碼,展開Test項目,其中的Doc檔案夾,就是全部的SwaggerUI的內容啦,index.html就是我們的文檔首頁:

 

  實現分Area(模組)來篩選所需展示的Controller

  再說Area分組前提一點小的改動

  Required為醒目紅色

Swagger 最大寬度增加到1100px,

左側增加模組篩選,點擊篩選後,將只顯示對應模組下。

具體的實現方式,就是根據你的模組名稱,來篩選api訪問路徑

如第一個user,就代表user模組了,第二個user才是控制器名稱。這樣的定義,使用了MVC5的新特性RouteAttribute和RoutePrefixAttribute,他們用於在controller中自訂路由,你可以下載源碼看到。

那我們左側功能表列的資料是哪兒來的呢。請看源碼SwaggerConfig中,我定義了這樣一個方法:

/// <summary>        /// 從API文檔中讀取控制器描述        /// </summary>        /// <returns>所有控制器描述</returns>        public static ConcurrentDictionary<string, string> GetControllerDesc(HashSet<string> moduleList)        {            string xmlpath = String.Format("{0}/bin/SwaggerCustom.Test.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"))                        {                            //模組資訊                            var moduleName = arrPath[length - 2];                            moduleList.Add(moduleName);                            //擷取控制器注釋                            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;        }

本來這個方法僅用於讀取Controller注釋的,但是既然這裡讀取了xml,我也就沒必要再讀一遍了。我增加了一個HashSet<string>類型的參數,在集合中資料每一個元素的資料是唯一的,所以使用它來存模組資訊,xml每次遍曆到Controller的時候,我都會將其Modules資訊讀取出來(比如namespace SwaggerCustom.Test.Controllers.Admin.AdminRoleController ),那麼倒數第二位的單詞就是模組名稱。這樣一來我們的模組資訊也包含在了json中,看AreaDescription,他說明了我有三個模組。

那麼接下來就是要做頁面渲染前的篩選工作了。我首先猜測渲染一定和返回json中的path(介面路徑)有關,所以我在swagger-ui-ext.js中搜尋path,總算找到了結果:

如下所示:遍曆時,通過篩選Module模組,對不符合我所想要的module進行直接return,而不向下執行,最終達到想要的目的。之所以說我沒有做深度最佳化的原因也是這裡,真正的深度最佳化應該是在後台代碼中所篩選,只返回自己想要的json結果,偷懶了。

所以,就是我點擊Admin選項後所篩選的結果,該模組下只有兩個Controller。

有關我個人所增加的js代碼,在Doc/lib/swagger-custom.js中。

//擷取Controller描述function SwaggerCustom() {    this.setControllerSummary = function () {        $.ajax({            type: "get",            async: true,            url: $("#input_baseUrl").val(),            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(9);                        strSummary = summaryDict[controllerName];                        if (strSummary) {                            $(item).children(".heading").children(".options").prepend(‘<li style="color:red;" class="controller-summary" title="‘ + strSummary + ‘">‘ + strSummary + ‘</li>‘);                        }                    }                });                swaggerCustom.loadMenu(data.AreaDescription);                expendtoggle();//註冊菜單收縮事件            }        });    };    //擷取當前參數    this.getQueryString = function (name) {        var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");        var r = window.location.search.substr(1).match(reg);        if (r != null) return unescape(r[2]); return null;    },    this.loadMenu = function (modules) {        var url = window.location.href;        url = url.substring(0, url.lastIndexOf(‘?‘));        $(‘body‘).prepend(‘<div class="menu-expender" id="menuExpend">←</div><div id="moduleMenu"><div onclick="menuClick(this)" data-url="‘ + url + ‘?module=all"  " data-module="all" class="menu-inner" >全部</div></div>‘);        var menuInner = ‘‘;        modules.forEach(function (item) {            menuInner += ‘<div onclick="menuClick(this)" data-url="‘ + url + ‘?module=‘ + item.toLowerCase() + ‘" data-module="‘ + item.toLowerCase() + ‘" class="menu-inner" >‘ + item + ‘</div>‘;        });        $(‘#moduleMenu‘).append(menuInner);        $(‘#moduleMenu‘).css("position", "fixed").css("top", "20%");    }}var swaggerCustom = new SwaggerCustom();var swaggerCustomGlobalData = {    currentModule: "all"}$(function () {    swaggerCustomGlobalData.currentModule = swaggerCustom.getQueryString(‘module‘) == null ? "all" : swaggerCustom.getQueryString(‘module‘);    //alert(swaggerCustomGlobalData.currentModule);});var swaggerStyle = {    showActionLink: function () {        $("li .toggleEndpointList").css("color", "#2392f7");    },    titleStyle: function () {        $("h2 .toggleEndpointList").css("color", "green");    },    showDetailLink: function () {        $("li .expandResource").css(‘color‘, ‘#996633‘);    },    paramTable: function () {        $(‘.fullwidth.parameters thead tr th:nth-child(1)‘).width(‘50px‘);        $(‘.fullwidth.parameters thead tr th:nth-child(2)‘).width(‘350px‘);        $(‘.fullwidth.parameters thead tr th:nth-child(3)‘).width(‘100px‘);        $(‘.fullwidth.parameters thead tr th:nth-child(4)‘).width(‘60px‘);        $(‘.fullwidth.parameters thead tr th:nth-child(5)‘).width(‘400px‘);        $(‘td textarea‘).width(‘380px‘);    },    init: function () {        this.showActionLink();        this.titleStyle();        this.showDetailLink();        //this.paramTable();    }}function menuClick(ele) {    window.location.href = (ele.dataset.url);}function expendtoggle() {    $(‘#menuExpend‘).toggle(function () {        $(this).html(‘→‘);        $(‘#moduleMenu‘).hide();    }, function () {        $(this).html(‘←‘);        $(‘#moduleMenu‘).show();    });}

 

  該如何使用??

  使用直接copy走SwaggerConfig.cs和Doc檔案放到你項目下,並且引用Swashbuckle就沒問題(可以直接拿源碼類庫,也可以直接從nuget上安裝)。並且你想使用這個模組劃分的功能,就一定要符合路由規則api/modulename/controller/action.因為模組的篩選就是通過modulename嘛。如果你只想使用swagger的準系統,看上一篇的分享就足夠了。拿到本次分享的源碼,你就可以在其中合理的修改源碼,自訂你的功能

  寫在最後

 

依然請原諒我這個標題黨。

如果我的點滴分享對你有點滴協助,歡迎點下方紅色按鈕關注,我將持續輸出分享。也歡迎為我,也為你自己點贊。關於本篇源碼有任何問題,歡迎留言。

ASP.NET WebApi 文檔Swagger深度最佳化

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.