ASP.NET WebApi 文檔Swagger深度優化

本文版權歸博客園和做者吳雙本人共同全部,轉載和爬蟲請註明博客園蝸牛原文地址,cnblogs.com/tdwscss

  寫在前面

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

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

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

1.文檔先後端分離github

2.項目結構ajax

3.實現分Area(模塊)來篩選所需展現的Controllerjson

 第三篇  :ASP.NET WebApi 文檔增長登陸 http://www.cnblogs.com/tdws/p/7395556.html後端

  文檔先後端分離

本篇文章提供源碼,下載連接:  https://github.com/coderws/CustomSwagger  (因爲博客園只能上傳10MB,就放github上吧,不求star,只爲了方便你們下載)api

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

  項目結構

你能夠看到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的基本功能,看上一篇的分享就足夠了。拿到本次分享的源碼,你就能夠在其中合理的修改源碼,自定義你的功能

  寫在最後

 

2017-03-13補充幾點

這個處理結果的展現,經過在action的描述文檔註釋上 ,增長節點<response code="201">Returns the newly created item</response>  

 

Swagger不識別ActionResult,須要肯定返回類型,因此在Core中 須要增長特性標籤 

 

 

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

若是個人點滴分享對你有點滴幫助,歡迎點下方紅色按鈕關注,我將持續輸出分享。也歡迎爲我,也爲你本身點贊。關於本篇源碼有任何問題,歡迎留言。

相關文章
相關標籤/搜索