一直以來,開發 WebAPI 我都很習慣用工具自動產生線上文件、線上測試介面以及客戶端程式庫,節省增刪介面方法後要同步調整文件及程式庫的工夫。

在 Swagger 流行之前,有好幾年的時間我都是靠土砲版 CodeGen 工具,用 Reflection 掃瞄 WebAPI 介面,從 XML Documentation 取得方法註解產生文件及客戶端元件。但土砲工具離要支援各式 WebAPI 應用仍有距離,功能完整性也待擴充。經過評估,回歸 Swagger 這類開放標準工具才是王道。

現在才入門已算晚,但好處是網路上已有許多前人整理的心得,以下是我的主要參考文件:

已有現成文章參考,Swagger 概念與安裝、產生文件及線上測試介面的細節就不多說了,僅記錄我用它自動產生程式碼時遇到的幾個小問題:

  1. 使用 Swashbuckle 5.6.0 版,GetXmlComentsPath() 傳回型別不再是 string,而是 Func,與網站文章有點出入,要修改如下:
private static Func<XPathDocument> GetXmlCommentsPath()
{
	return () => new XPathDocument(HostingEnvironment.MapPath(@"~/App_Data/XmlDocument.xml"));
}
  1. Swagger 只支援 ApiController,但大家都知道我是非 RESTful 陣營成員(參考:閒聊 - Web API 是否一定要 RESTful?),不以 HTTP 方法改用 Action 名稱區隔(術語為 RPC-style API)會導致一個 Controller 出現多個 Action 名稱不同但都是走 HttpPost 的方法,形成路由混淆,而檢視 Swagger UI 時也會出現錯誤: Not supported by Swagger 2.0: Multiple operations with path 'api/MyApiName' and method 'POST'. See the config setting - "ResolveConflictingActions" for a potential workaround,官方文件:Routing in ASP.NET Web API Routing by Action Name 一節有提到定義 "api/{controller}/{action}/id" 路由,必要時透過 [ActionName("DoSomething")] 自訂名稱的解法,但實測在 Swashbuckle 不管用,需透過 Action 加註 [Route("api/MyApiName/DoSomething")] 自訂路由克服。

  2. Swashbuckle 會依據 WebAPI 介面自動產生 Swagger.json,下載位置在 httq://your-webapi-server/swagger/docs/v1,後續可用於程式碼產生。

  3. Swagger Codegen 可依據 Swagger JSON 定義檔自動產生 Client 程式碼。 操作前先取得 Swagger CodeGen 程式:

    Invoke-WebRequest -OutFile swagger-codegen-cli.jar http://central.maven.org/maven2/io/swagger/swagger-codegen-cli/2.3.1/swagger-codegen-cli-2.3.1.jar
    

    再執行 swagger-codegen-cli.jar 傳入 Swagger.json 指定語言平台產生程式碼:

    java -jar .\\swagger-codegen-cli.jar generate -i http://localhost:25587/swagger/docs/v1 -l csharp -o E:\ApiClient
    

    -i 指定 Swagger.json 網址,-l 指定語言 csharp 可產生 C# 程式庫。Swagger CodeGen 支援 C#、C++、Java、Golang、PHP、Objective-C、Perl、PHP、PowerShell、Python、TypeScript/JavaScript 等各式呼叫端程式庫,我的土砲版只支援 C#,這也是吸引我改用 Swagger 的原因。

  4. 用 VS2017 開啟 Swagger CodeGen 產生的 C# 專案,發現原本的 NuGet 參照有些問題,JsonSubTypes 及 RestSharp 參照有誤。專案原本 Target 是 .NET 4.5,實測升級到 4.5.2 可解決。

  5. Swagger CodeGen 產生的 C# 客戶端專案還包含 NUnit 測試, 但我發現 NUnit NuGet 套件要升到 3.x,不然會出現 NUnit couldn't find any tests in IO.Swagger.dll 警示且無法測試。

    NUnit 要升級,但 RestSharp 升到 1.6 則會出現版本相容問題,如不想調程式留在 1.5.x 就好。

Some tips of using Swagger on ASP.NET MVC WebAPI.


Comments

# by ChrisTorng

我用微軟開發的 AutoRest https://github.com/Azure/AutoRest 產出 C# client,另支援 PowerShell, Go, Java, Node.js, TypeScript, Python, Ruby 及 PHP。因為不想裝 Java,因此沒玩過 Swagger 原版的 C#,是否有可能比較兩者的產出程式呢? 但我還是蠻懷念 Refit https://reactiveui.github.io/refit/ 的輕便直覺,只可惜沒有支援 Swagger。

# by aboyliu

想請問黑暗大關於第2步驟「但實測在 Swashbuckle 不管用,需透過 Action 加註 [Route("api/MyApiName/DoSomething")] 自訂路由克服。」,這部分我一直無法嘗試成功,能否請您更詳細說明一點,謝謝。

# by Jeffrey

to aboyliu, 是指加了 [Route("api/MyApiName/DoSomething")] 仍然出現 Multiple operations with path 'api/MyApiName' and method 'POST' 錯誤嗎?

# by aboyliu

感謝您的回覆,我詳細描述一下我遭遇到的問題: 1.為了單純化,我另開一個新的Web API專案。 2.為了測試我建了兩個Controller,分別繼承ApiController和Controller。 3.DefaultApiController沒問題在http://Domain/swagger順利呈現DefaultApi的內容;但DefaultController在加了[Route("api/MyApiName/DoSomething")]後沒有呈現,也沒有出現您所述的「Multiple operations with path 'api/MyApiName' and method 'POST'」訊息。 4.我不知道是[Route("api/MyApiName/DoSomething")]中的MyApiName、DoSomething要置換掉,還是我漏掉了什麼設定步驟。 5.我用的是Swashbuckle v5.6.0。 感謝您抽空回覆我,不知道這樣的資訊足不足夠您還原問題,謝謝。

# by Jeffrey

to aboyliu, Swagger 只支援 ApiController 的子類別(請見第2點第一句),我過往慣用 ASP.NET MVC Controller 寫 WebAPI ( https://blog.darkthread.net/blog/build-webapi-with-aspnetmvc-tutorial/),為了 Swagger 才改用 ApiController。

# by aboyliu

原來是我會錯意了,感謝您的說明,占用您寶貴的時間很抱歉。

Post a comment