[.NET] 在Swagger中自訂每個控制器所能輸入的Header欄位

有用Visual Studio + .NET開發的人一定會知道Swagger這一個非常好用的測試畫面套件
但是這個套件有一個缺點,如果只是單純的參數輸入很方便,萬一在控制器中有需要帶入Header的話,Swagger就無用武之地了

在這篇文章裡,會教大家怎麼用很簡單的方式,就讓你的Swagger中,每一個控器器中長出不同的Header輸入欄位,並且還可以進行欄位資料類型的檢核與選單的製作

要讓每一個控制器都能長出不同Header的輸入介面,只要簡單的一些程式碼就可以作到了

1.先在專案的程式碼中加入一個[HeaderAttribute.cs]的類別庫

2.在這個類別庫中加入下面的程式碼內容

public class HeaderAttribute : Attribute
{
    public string headersConfig { get; set; }
}

這一個類別庫的用途很簡單,就只是用來在每一個不同的控制器方法中,可以讓開發人員自訂要在Swagger畫面中輸入的Header資料有哪些

3.在專案中加入一個類別庫[HeaderFilter.cs]

4.在HeaderFilter.cs的類別庫中,加入下面的程式碼

using Swashbuckle.Swagger;
using System.Web.Http.Description;

public class HeaderFilter : IOperationFilter
{
    public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription)
    {
        if (!apiDescription.ActionDescriptor.GetCustomAttributes<HeaderAttribute>().Any())
        {
            return;
        }

        if (operation.parameters == null)
        {
            operation.parameters = new List<Parameter>();
        }

        HeaderAttribute attr = apiDescription.ActionDescriptor.GetCustomAttributes<HeaderAttribute>().FirstOrDefault();
        // 取出Headers,並進行切割
        List<string> strHeaders = attr.headersConfig.Split("|".ToCharArray()).ToList();
        for (int i = 0; i < strHeaders.Count; i++)
        {
            // 切割參數
            List<string> strHeaderParam = strHeaders[i].Split(",".ToCharArray()).ToList();

            // 將設定的欄位及屬性加入到Header的輸入欄位之中
            Parameter objParam = new Parameter()
            {
                name = strHeaderParam[0],
                @in = "header",
                type = strHeaderParam[1],
                required = true,
            };

            if (strHeaderParam.Count > 2)
                objParam.@enum = strHeaderParam[2].Split("/".ToCharArray()).ToList<object>();

            operation.parameters.Add(objParam);
        }
    }
}

這個Filiter類別庫,繼承了Swagger的IOperationFilter介面,所以當Swagger在產生介面的時候,我們在Apply方法中,增加需要產生Header的介面讓使用者使用

在這個方法的下方,取出了HeaderAttribute類別中的headersConfig屬性,並將這個字串屬性進行分割,以便我們進行不同控制器方式中,不同Header輸入的套用
這裡的用法,是用 "|" (直線) 作為不同欄位的區隔,用 "," (逗號) 作為定義參數的區隔,另外,在第三個參數中,我用 "/" (斜線) 作為列舉型別參數的設定
也就是說,如果我希望這個方法可以使用的Header有三個,分別是字串、數字、以及布林值,設定的方法就可以用 "header1,string|header2,integer|header3,boolean,true/false"這樣的設定方式來處理

5.打開[App_Start\Swagger.cs]這個檔案,並加上下面這行的程式碼

c.OperationFilter<Swagger.HeaderFilter>();

增加的位置如下圖所示

到這邊,所有的準備工作就已經完成了,最後只要打開控制器,並在方法中增加希望顯示的Header輸入欄位設定就可以了,在步驟4中所說明的欄位設定方式,我將這個設定內容放到方法的Attribute設定中

[Swagger.Header(headersConfig="header1,string|header2,integer|header3,boolean,true/false")]
public IEnumerable<string> Get()
{
    return new string[] { "value1", "value2" };
}

目的是希望有一個header1的輸入框可以輸入文字,header2的輸入框可以輸入數字,而header3的參數則是布林值可以透過下拉選單的方式作選擇,最後可以得到下面的結果Header的輸入框出現了,也有依據我們想要的設定顯示,如果在不同的方法中設定不同的headerConfig的話,也會出現不同的Header輸入表單,如下面的程式進行的設定

public class HeaderController : ApiController
{
    [Swagger.Header(headersConfig="header1,string|header2,integer|header3,boolean,true/false")]
    public IEnumerable<string> Get()
    {
        return new string[] { "value1", "value2" };
    }

    [Swagger.Header(headersConfig = "no1,string|no2,integer,1/2/3/4/5/6/7")]
    public string Get(int id)
    {
        var strValues = new string[] { "1", "2" };
        return strValues[2];
        // throw new System.NotImplementedException();
        // return "value";
    }
}

我將兩個不同的方法,設定不同的Header輸入欄位,得到的結果可以看到,兩個不同的方法真的都出現不一樣的Header的輸入框了

在Swagger中針對不同的方法設定Header的輸入,對於測試與開發人員來說,可以省掉很多在Header上的輸入與處理,尤其是有些安全性較高的方法,常常會運用Header進行額外資料的傳送,對於這樣的情境下,自訂各別方法的Header輸入欄位在操作上就會顯得格外的方便了

參考資料:
Web Api How to add a Header parameter for all API in Swagger

Github檔案下載:
https://github.com/madukapai/maduka-WebAPI