在部落格分享心得有一項好處,是不時會獲得讀者們熱心回應,補上被我忽略的寶物利器,有些未必學得了跟得上,但保持眼界開闊總是好的,避免淪為資深井底蛙。

Swagger 初試筆記一文發表後,網友再補充了兩件好東西:

  • AutoRest
    微軟開發的 OpenAPI 規格客戶端程式碼產生工具 (感謝 ChrisTorng 分享)
  • NSwag
    可以 Middleware 形式整合進 ASP.NET Core,另外有 NSwag Studio GUI 程式碼產生器。(感謝 Jim 分享)

眼前的應用以產生 .NET 客戶端配合 VS2017 開發為主,前篇文章已試過 Swagger Codegen,這篇再把 AutoRest 跟 NSwag 補上。

AutoRest

AutoRest 是個 NPM 模組,使用 npm install -g autorest安裝,產生 C# 客戶端前要從 URL 取得 Swagger 定義檔存成 swagger.json,接著下指令:autorest --input-file=swagger.json --output-folder=e:\ApiClientAR --csharp 即可產生一連串檔案:

與 Swagger Codegen 不同,輸出結果不包含 .csproj,需將檔案加入現有專案使用,相較於 Swagger Codegen 建立獨立單一程式庫專案,這種做法更具彈性。簡單應用時可以融入現有專案減少解決方案專案數及部署 DLL 數目,若需多專案共用,另建 Class Library 放入程式就好。

除了 Json.NET,AutoRest 產生的客戶端還需要引用 Microsoft.Rest.ClientRuntime NuGet 程式套件。

使用上很簡單,new 建立物件,呼叫方法,得到結果,收工。

NSwag

提供 GUI 介面是 NSwag 的一大賣點, 下載並執行 MSI 安裝檔(亦可使用 Chocolatey安裝)後,在眾多解決方案中 NSwag Studio 提供很不一樣的操作體驗。輸入 Swagger 規格文件 URL、按下 Copy Local Copy 內容會被下載到下方輸入框(亦可直接將 Swagger.json 內容貼進輸入框)、選擇 Runtime (有 x86、x64、.NET Core 1.0 ~ 2.2 等選擇)、勾選 Outputs / CSharp Client、輸入 Namespace,按下【Generate Outputs】:

程式碼會出現在 Output 欄位。NSwag 產生的程式碼進一步簡化成單一 .cs 檔,使用時在專案裡新增類別 .cs 檔貼上內容,加上 Json.NET 及 System.Runtime.Serialization 參照即可編譯,相較之下,NSwag 對第三方套件的依賴也是最低的。

此外,NSwag C# 程式庫可以微調的選項蠻多,面對不同應用情境時彈性會大一些。

預設的做法在建構 WebAPI 客戶端物件時需傳入 HttpClient 物件,並自行控制其生命週期(但也可調成自動建立與消滅),一樣是建立物件、呼叫、得到結果、收工,很方便。

.NET 3.5 支援問題

考慮部分專案仍使用 .NET 3.5,而 Swagger Codegen、AutoRest、NSwag 產生的 C# 程式碼都要求 .NET Runtime 4.0 起跳(光看到 Task 就知 .NET 3.5 過不了關)是一項困擾。研究之後,發現 Swagger Codegen 有解,除了 csharp 外,還有另一個 csharp-net20 選擇,不過試了一下,它被設計成要用 Mono 編譯,感覺跟 Visual Studio 整合得花點功夫。追進原始碼,在 csharp 範本發現依 .NET 版本控制程式寫法的開關,這才發現 csharp 有控制選項,用 java -jar swagger-codegen-cli.jar config-help -l csharp 列出參數:

摘錄幾個可能會用到的:

  • packageName
    C# package name (convention: Title.Case). (Default: IO.Swagger) 改掉 IO.Swagger 命名空間
  • targetFramework
    The target .NET framework version. (Default: v4.5)
    v3.5 - .NET Framework 3.5 compatible
    v4.0 - .NET Framework 4.0 compatible
    v4.5 - .NET Framework 4.5+ compatible
    v5.0 - .NET Standard 1.3 compatible
    uwp - Universal Windows Platform (IMPORTANT: this will be decommissioned and replaced by v5.0)
  • modelPropertyNaming
    Naming convention for the property: 'camelCase', 'PascalCase', 'snake_case' and 'original', which keeps the original name (Default: PascalCase) 屬性名稱大小寫,Camel、Pascal 等
  • useDateTimeOffset
    Use DateTimeOffset to model date-time properties (Default: false)
  • useCollection
    Deserialize array types to Collection<T> instead of List<T>. (Default: false)
  • returnICollection
    Return ICollection<T> instead of the concrete type. (Default: false)
  • ptionalMethodArgument
    C# Optional method argument, e.g. void square(int x=10) (.net 4.0+ only). (Default: true)
  • optionalAssemblyInfo
    Generate AssemblyInfo.cs. (Default: true)
  • optionalProjectFile Generate .csproj. (Default: true)
  • optionalEmitDefaultValues Set DataMember's EmitDefaultValue. (Default: false)
  • netCoreProjectFile
    Use the new format (.NET Core) for .NET project files (.csproj). (Default: false) 是否建成 .NET Core csproj
  • validatable Generates self-validatable models. (Default: true) 是否在Model實作IValidate

用 -DtargetFramework=v3.5 參數即可指定 targetFramework 版本,另一種做法是將設定寫成 config.json:

{
    "packageName": "MyApp.Client",
    "targetFramework": "v3.5"
}

執行時加上 -c config.json,例如: java -jar swagger-codegen-cli.jar generate -i http://localhost:25587/swagger/docs/v1 -l csharp -c config.json -o e:\ApiClient

實測指定 targetFramework = v3.5 後,專案可使用 .NET 3.5 編譯及測試無誤,但自動測試專案要配合 NUnit 3.x 需維持 .NET 4.0。

評估

經過一番試用,算是對 Swagger Codegen、AutoRest、NSwag 有了粗淺認識,以「要產生 C# 客戶端程式庫供 Visual Studio 開發 .NET 3.5/4.0/4.5 程式」為前題,簡單整理三者比較:

  • Swagger Codegen
    專案最完整,甚至包含自動測試,為獨立專案自帶 .csproj 可直接以 VS2017 開啟。需依賴 RestSharp、JsonStubTypes NuGet 程式庫,可直接支援 .NET 3.5。
  • AutoRest
    產生結果為多個檔案,可拖入現有專案或新建類別程式庫專案,可調整項目較少,依賴 Microsoft.Rest.ClientRuntime NuGet 套件。
  • NSwag
    產生結果為單一 .cs 檔,直接加入既有專案即可,提供 GUI 操作介面友善度高,可調整項目多且幾乎不依賴第三方套件。(Json.NET 為每個專案必備,不視為額外套件)

三者相比,我特別喜歡 NSwag 集中單一檔案的做法,程式產生器輸出結果再人工個別維護的機率不高,拆成多個檔案好處不大徒增複雜度,而減少檔案數目有助簡化操作與管理。提供 GUI 工具及不依賴第三方套件也讓 NSwag 格外討喜,唯一美中不足是無法直接支援 .NET 3.5。

初步評估,我打算開始在專案採用 NSwag 並設法克服 .NET 3.5 相容問題,但魔鬼總在細節裡,會不會踢到鐵板轉向或發現更好的替代方案,Who Knows? 做下去就對了,Just Do It!

For scenarios to generate C# client library from Swagger json defintion, I surveyed AutoRest and NSwag and Swagger Codegen to find the proper solution.


Comments

Be the first to post a comment

Post a comment