Oh my God, Swagger API文檔竟然可以這樣寫?

最好的總會在不經意間出現。

作爲後端程序員,免不了與前端同事對接API, 一個書寫良好的API設計文檔可有效提高與前端對接的效率。

爲避免聯調時來回撕逼,今天我們聊一聊正確使用Swaager的姿勢。

基礎Swagger用法

ConfigureServices配置Swagger文檔,在Configure啓用中間件

 // Install-Package Swashbuckle.AspNetCore 略 
 services.AddSwaggerGen(
       options =>
       {
           options.SwaggerDoc("v1", new OpenApiInfo { Title = "EAP API", Version = "v1" });
       }
  );     
---

app.UseSwagger();
app.UseSwaggerUI(options =>
{
    options.SwaggerEndpoint("/swagger/v1/swagger.json", "EAP API");
});

應用會在/Swagger頁面加載最基礎的API文檔。

以一個最簡單的Post請求爲例,細數這最基礎SwaggerUI的弊病

[HttpPost]
public async Task<bool> AddHotmapAsync([FromBody] CreateHotmapInput createHotmapInput)
{
     var model = ObjectMapper.Map<CreateHotmapInput, Hotmap>(createHotmapInput);
     model.ProfileId = CurrentUser.TenantId;
     return await _hotmaps.InsertAsync(model)!= null;
}

產生如圖示SwaggerUI:

  1. Post請求的Payload字段值相對複雜,竟不給前端傳值example?
  2. 沒有指示前端請求的Content-Type,前端會不會給你另外一個surprise?
  3. 服務器沒有指示響應的Content-Type,?
  4. 服務器沒有指示響應的預期狀態碼,前端會不會抓狂?

下文就來根治這些頑疾, 書寫一個自述性、優雅的API文檔。

Swagger最佳實踐

三下五除二,給出示例:

        /// <summary>
        /// 添加熱力圖
        /// </summary>
        /// <remarks>
        /// Sample request:
        /// ```
        ///  POST /hotmap
        ///  {
        ///      "displayName": "演示名稱1",
        ///      "matchRule": 0,
        ///      "matchCondition": "https://www.cnblogs.com/JulianHuang/",
        ///      "targetUrl": "https://www.cnblogs.com/JulianHuang/",
        ///      "versions": [
        ///      {
        ///         "versionName": "ver2020",
        ///         "startDate": "2020-12-13T10:03:09",
        ///         "endDate": "2020-12-13T10:03:09",
        ///          "offlinePageUrl": "3fa85f64-5717-4562-b3fc-2c963f66afa6",  //  沒有綁定圖片和離線網頁的對應屬性傳 null
        ///          "pictureUrl": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
        ///          "createDate": "2020-12-13T10:03:09"
        ///      }
        ///    ]
        ///  }
        ///```
        /// </remarks>
        /// <param name="createHotmapInput"></param>
        /// <returns></returns>
        [Consumes("application/json")]
        [Produces("text/plain")]
        [ProducesResponseType(typeof(HotMap), 200)]
        [HttpPost]
        public async Task<bool> AddHotmapAsync([FromBody] CreateHotmapInput createHotmapInput)
        {
            var model = ObjectMapper.Map<CreateHotmapInput, Hotmap>(createHotmapInput);
            model.ProfileId = CurrentUser.TenantId;
            await _hotmaps.InsertAsync(model);
            return "done !, This is Test";
        }
  1. 通過給API添加XML註釋

注意如果註釋內容包含代碼,可以使用Markdown的代碼語法```,在註釋裏面優雅顯示代碼.

  1. 通過Consumes,Produces特性指示action接收和返回的數據類型,也就是媒體類型。

Consumes、Produces是指示請求/響應支持的content types的過濾器,位於Microsoft.AspNetCore.Mvc命名空間下。

  1. 通過ProducesResponseType特性指示服務器響應的預期內容和狀態碼

API文檔結果:

這樣的SwaggerUI才正確表達了後端程序員的內心輸出。


在Swagger文檔上顯示註釋

  1. 生成XML註釋文檔
    在項目上[右鍵]-[屬性]-[生成標籤頁]-[勾選XML文檔文件];
    或者直接在項目csproj文件--[PropertyGroup]添加<GenerateDocumentationFile>true</GenerateDocumentationFile>
  2. AddSwaggerGen方法添加下行,啓用註釋文件
// Set the comments path for the Swagger JSON and UI.
var xmlFile = $"{this.GetType().Assembly.GetName().Name}.xml";
var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
opt.IncludeXmlComments(xmlPath);

這裏囉嗦一下,如果是Abp Vnext解決方案(API是定義在HttpApi項目/Application項目),故我們要爲Abp Vnext解決方案加載帶xml註釋的Swagger Json,需要指示xmlFile爲HttpApi.xml或者applicaiton.xml

以上就是小碼甲總結的書寫Swagger文檔的優雅姿勢:

  • 編寫API 傳值example
  • 約束請求/響應 支持的媒體類型
  • 指示API的預期輸出內容、預期狀態碼

API自述,約束輸入輸出,前端同事再也不會追着你撕逼了!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章