選單
GSS 技術部落格
在這個園地裡我們將從技術、專案管理、客戶對談面和大家分享我們多年的經驗,希望大家不管是喜歡或是有意見,都可以回饋給我們,讓我們有機會和大家對話並一起成長!
若有任何問題請來信:gss_crm@gss.com.tw
5 分鐘閱讀時間 (1047 個字)

Swagger for Web API Document - Part Ⅰ

wide-view-mockup-of-the-creative-workspace-with-macbook-pro
以往,
我們在開發 API 的過程中,
通常需要提供一份接口文件給其他團隊瀏覽或測試,
而這份文件往往都需要花費大量時間與成本在專案開發中、後期來完成它,
最近剛好小編也正著手開發一個新的 Web API 專案,
有預先針對 API Document 的實作進行 Survey,
希望能在開發 API 的同時即能產出一份「符合 RESTful API 規範的線上文件」,



經過一番審慎評估後,
在 API BlueprintSwagger 間選擇了 Swagger 作為該專案的 API Document 工具,
其原因在於 Swagger 的「程式碼與文件兩者並存」的開發方式深深吸引了我,
再進一步研究過 微軟官方 建議的 Swagger 服務套件「Swashbuckle」後,
使我更能感受到以 XML 文件註解的方式搭配 Annotation 的定義來實現「程式即文件」的快速開發精隨,
※ 註:習慣 Markdown 語法, 且需提供文件下載(如:Html)即建議採用 API Blueprint
接下來將簡單介紹如何安裝及使用「Swashbuckle」套件來完成 Swagger API Document 的建置!

套件安裝

首先, 透過 Visual Studio 管理 Nuget 套件搜尋「Swashbuckle」並安裝:



或透過 Visual Studio 的套件管理器主控台下指令:

[code language="bash"]
PM> Install-Package Swashbuckle -Version 5.6.0
[/code]

環境設定

安裝完 Nuget  Package 後, 會發現 App_Start 目錄下會多一個 「SwaggerConfig.cs」檔案, 為了提供 Swagger 正確「產出」及「讀取」相關 API 接口資訊(XML Document), 需要進行以下 4 個操作步驟:
  1. 於 GlobalConfiguration.Configuration.EnableSwagger 設定中, 加入 IncludeXmlComments 設定:

    [code language="cpp"] 
    
    GlobalConfiguration.Configuration.EnableSwagger(
     c => {
      // 取得 Swagger XML 產出的路徑(如設定已存在請反註解) 
      c.IncludeXmlComments(GetXmlCommentsPath()); 
    });
    
    [/code]
  2. 並在設定檔下方實作 GetXmlCommentsPath 的方法:

    [code language="cpp"] 
    
    /// <summary>
    /// 取得 Swagger XML 產出的路徑
    /// </summary>
    internal static string GetXmlCommentsPath()
    {
     return System.String.Format(@"{0}\App_Data\SwaggerXmlDoc.xml", System.AppDomain.CurrentDomain.BaseDirectory);
    }
    
    [/code]
  3. 在專案上方點選右鍵, 打開屬性設定, 在【建置】頁籤中將輸出區塊的【XML 文件檔案】打勾, 並填入 Swagger XML 產出的路徑(App_Data/SwaggerXmlDoc.xml), 即完成設定:
  4. 完成上述設定後, 將專案啟動執行, 並於網址根目錄後方加上 Swagger 即可看到 Swagger Online API Document(如:http://localhost:59820/Swagger):

建立 API 功能

首先, 我們先將 Demo Code 提供給大家參考與練習:
[code language="cpp"]

/// <summary>
/// 產品 API 列表
/// </summary>
[RoutePrefix("api/Products")]
[SwaggerResponse(HttpStatusCode.OK, Description = "要求成功,回應要求結果。")]
[SwaggerResponse(HttpStatusCode.NoContent, Description = "成功處理要求,無回應任何結果。")]
[SwaggerResponse(HttpStatusCode.Unauthorized, Description = "驗證失敗,請確認 API Key 有效性。")]
[SwaggerResponse(HttpStatusCode.BadRequest, Description = "請確認 Uri 及相關 Parameters 是否正確。")]
public class ProductsController : ApiController
{
 /// <summary>
 /// 取得所有產品資料
 /// </summary>
 /// <param name="name">名稱</param>
 /// <param name="desc">描述</param>
 /// <remarks>可使用產品「名稱」與「描述」關鍵字查詢產品資料</remarks>
 /// <returns>所有產品資料</returns>
 [HttpGet]
 public HttpResponseMessage Get(string name, string desc = null)
 {
  return Request.CreateResponse(HttpStatusCode.OK);
 }

 /// <summary>
 /// 取得指定產品資料
 /// </summary>
 /// <param name="id">指定產品編號</param>
 /// <returns>指定產品資料</returns>
 [HttpGet]
 [SwaggerResponse(HttpStatusCode.OK, Description = "要求成功,回應要求結果。(客製)", Type = typeof(ProductModel.EditView))]
 public HttpResponseMessage Get(int id)
 {
  return Request.CreateResponse(HttpStatusCode.OK, new ProductModel.EditView());
 }

 /// <summary>
 /// 新增產品
 /// </summary>
 /// <param name="model">產品編輯模型</param>
 /// <returns>新增產品結果</returns>
 [HttpPost]
 public HttpResponseMessage Post([FromBody]ProductModel.EditView model)
 {
  int insertedId = new Random().Next(int.MinValue, int.MaxValue);
  return Request.CreateResponse(HttpStatusCode.OK, new { id = insertedId });
 }

 /// <summary>
 /// 修改產品
 /// </summary>
 /// <param name="id">指定產品編號</param>
 /// <param name="model">產品編輯模型</param>
 /// <returns>修改產品結果</returns>
 [HttpPut]
 public HttpResponseMessage Put(int id, [FromBody]ProductModel.EditView model)
 {
  return Request.CreateResponse(HttpStatusCode.OK);
 }

 /// <summary>
 /// 刪除產品
 /// </summary>
 /// <param name="id">指定產品編號</param>
 /// <returns>新增產品結果</returns>
 [HttpDelete]
 public HttpResponseMessage Delete(int id)
 {
  return Request.CreateResponse(HttpStatusCode.OK);
 }

 /// <summary>
 /// 取得產品進貨資訊
 /// </summary>
 /// <param name="id">指定產品編號</param>
 /// <returns>產品進貨資訊</returns>
 [HttpGet]
 [Route("{id}/Purchase")]
 public HttpResponseMessage GetPurchaseInfo(int id)
 {
  return Request.CreateResponse(HttpStatusCode.OK);
 }
}
[/code]


以下, 我們將以代碼與畫面對應的方式來逐步說明程式於 Swagger UI 上的實現:
關於 API 的描述與參數說明
在 Controller / Action 上填寫 XML Annotation 內容, 在 Swagger UI 即可呈現出對應的內容, 關於參數的部分, Swagger 也可完整呈現必填或可選的提示(也包含 Model [Required] Annotation 的支援):


對應 API 各種 HTTP Status 的 Response
可以在 Controller / Action 加上 Swagger Annotations 命名空間中的 [SwaggerResponse] Annotation 來定義每個 HTTP Status 對應的 Response 訊息。

當在 Action 上套用 [SwaggerResponse] Annotation 時, 有明確給予 Response Type 的資訊, 在 Swagger UI 上即會呈現完整的 Response Class 資訊(Model Schema  & Example Value):


支援 ASP.NET Routing 機制
依循 REST Resource Naming Guide, 專案如果需要支援 Nested Resources API(如:GET /api/collectionA/{id}/collectionB/{id}), 我們可透過 ASP.NET Routing 的機制, 搭配 [RoutePrefix] 與 [Route] Attributes 來實現, 而 Swagger UI 也無痛支援  ASP.NET Routing 的機制:


小結

根據上述說明操作, 即可完成基本的 Swagger API Document 的建置, 在下一篇文章中, 我們將進一步地介紹如何在 Swagger UI 介面中輸入並支援「API Key & Token」以及在畫面上提供「API's Request & Response Examples」來提升使用者體驗。

廢話不多說, 一起前往 Swagger for Web API Document - Part Ⅱ 吧!
Swagger for Web API Document - Part Ⅱ
更新 Mac App 憑證

相關文章

 

評論

尚無評論
已經注冊了? 這裡登入
Guest
2024/05/17, 週五

Captcha 圖像