REST API を使用するアプリケーションは、非常に一般的なシナリオです。 通常、アプリケーションが REST API の呼び出しに使用できるクライアント コードを生成する必要があります。 このチュートリアルでは、MSBuild を使用したビルド プロセス中に REST API クライアントを自動的に生成する方法について説明します。 NSwag という REST API のクライアント コードを生成するツールを使います。
完全なサンプル コードは、GitHub の .NET サンプル リポジトリ REST API クライアント生成 で入手できます。
この例は、パブリック Pet Store APIを使用するコンソール アプリを示しています。このアプリは、OpenAPI 仕様を発行します。
このチュートリアルでは、タスク、ターゲット、プロパティ、ランタイムなどの MSBuild 用語に関する基本的な知識を前提としています。必要な背景情報については、MSBuild の概念に関する記事 参照してください。
ビルドの一部としてコマンド ライン ツールを実行する場合は、2 つの方法を検討する必要があります。 1 つは、MSBuild Exec タスクを使用することです。これにより、コマンド ライン ツールを実行し、そのパラメーターを指定できます。 もう 1 つの方法は、ToolTaskから派生したカスタム タスクを作成することです。これによって、より詳細な制御が得られます。
前提 条件
タスク、ターゲット、プロパティなどの MSBuild の概念を理解している必要があります。 MSBuild の概念 参照してください。
この例では、VISUAL Studio と共にインストールされる MSBuild が必要ですが、個別にインストールすることもできます。 Visual Studio を使用せずに MSBuild をダウンロードするを参照してください。
オプション1:実行タスク
Exec タスク は、指定した引数を使用して指定されたプロセスを呼び出し、完了するまで待機してから、プロセスが正常に完了した場合は true
を返し、エラーが発生した場合は false
します。
NSwag コード生成は MSBuild から使用できます。NSwag.MSBuild 参照してください。
完全なコードは、PetReaderExecTaskExample フォルダーにあります。ダウンロードして見ることができます。 このチュートリアルでは、段階的に説明し、途中で概念を学習します。
PetReaderExecTaskExample
という名前の新しいコンソール アプリケーションを作成します。 .NET 6.0 以降を使用します。同じソリューションに別のプロジェクトを作成します:
PetShopRestClient
(このソリューションには、生成されたクライアントがライブラリとして含まれます)。 このプロジェクトでは、.NET Standard 2.1 を使用します。 生成されたクライアントは、.NET Standard 2.0 ではコンパイルされません。PetReaderExecTaskExample
プロジェクトで、プロジェクトPetShopRestClient
に対する依存関係を追加します。PetShopRestClient
プロジェクトに、次の NuGet パッケージを含めます。- MSBuild からコード ジェネレーターにアクセスできる Nswag.MSBuild
- 生成されたクライアントをコンパイルするために必要な Newtonsoft.Json
- 生成されたクライアントをコンパイルするために必要な System.ComponentModel.Annotations
PetShopRestClient
プロジェクトで、コード生成用のフォルダー (PetShopRestClient
という名前) を追加し、自動的に生成された Class1.cs を削除します。プロジェクトのルートに petshop-openapi-spec.json という名前のテキスト ファイルを作成します。 ここに から OpenAPI 仕様をコピーし、ファイルに保存します。 ビルド中にオンラインで読み取るのではなく、スペックのスナップショットをコピーすることをお勧めします。 常に、入力のみに依存する一貫して再現可能なビルドが必要です。 API を直接使用すると、現在動作するビルドが、同じソースから明日失敗するビルドに変換される可能性があります。 petshop-openapi-spec.json に保存されたスナップショットを使用すると、スペックが変更された場合でもビルドするバージョンを持つことができます。
次に、PetShopRestClient.csproj を変更し、MSBuild ターゲット を追加して、ビルド プロセス中にクライアントを生成します。
まず、クライアントの生成に役立ついくつかのプロパティを追加します。
<PropertyGroup> <PetOpenApiSpecLocation>petshop-openapi-spec.json</PetOpenApiSpecLocation> <PetClientClassName>PetShopRestClient</PetClientClassName> <PetClientNamespace>PetShopRestClient</PetClientNamespace> <PetClientOutputDirectory>PetShopRestClient</PetClientOutputDirectory> </PropertyGroup>
次のターゲットを追加します。
<Target Name="generatePetClient" BeforeTargets="CoreCompile" Inputs="$(PetOpenApiSpecLocation)" Outputs="$(PetClientOutputDirectory)\$(PetClientClassName).cs"> <Exec Command="$(NSwagExe) openapi2csclient /input:$(PetOpenApiSpecLocation) /classname:$(PetClientClassName) /namespace:$(PetClientNamespace) /output:$(PetClientOutputDirectory)\$(PetClientClassName).cs" ConsoleToMSBuild="true"> <Output TaskParameter="ConsoleOutput" PropertyName="OutputOfExec" /> </Exec> </Target> <Target Name="forceReGenerationOnRebuild" AfterTargets="CoreClean"> <Delete Files="$(PetClientOutputDirectory)\$(PetClientClassName).cs"></Delete> </Target>
このターゲットでは、ビルド順序を定義する方法として BeforeTarget と AfterTarget 属性が使用されていることに注意してください。
generatePetClient
と呼ばれる最初のターゲットはコア コンパイル ターゲットの前に実行されるため、コンパイラが実行される前にソースが作成されます。 入力パラメーターと出力パラメーターは、インクリメンタル ビルド に関連しています。 MSBuild では、入力ファイルのタイムスタンプと出力ファイルのタイムスタンプを比較し、ターゲットをスキップ、ビルド、または部分的にリビルドするかどうかを決定できます。NSwag.MSBuild
NuGet パッケージをプロジェクトにインストールした後、.csproj
ファイルの変数$(NSwagExe)
を使用して、MSBuild ターゲットで NSwag コマンド ライン ツールを実行できます。 これにより、NuGet を使用してツールを簡単に更新できます。 ここでは、Exec
MSBuild タスクを使用して、クライアント Rest Api を生成するために必要なパラメーターを指定して NSwag プログラムを実行します。 NSwag コマンドとパラメーター を参照してください。<Exec>
から出力をキャプチャするには、<Exec>
タグにConsoleToMsBuild="true"
を追加し、その後、<Output>
タグのConsoleOutput
パラメーターを使用して出力をキャプチャします。ConsoleOutput
は出力をItem
として返します。 空白はトリミングされます。ConsoleOutput
は、ConsoleToMSBuild
が true の場合に有効になります。forceReGenerationOnRebuild
と呼ばれる 2 番目のターゲットは、クリーンアップ中に生成されたクラスを削除して、再構築ターゲットの実行中に生成されたコードを強制的に再生成します。 このターゲットは、CoreClean
MSBuild の定義済みターゲットの後に実行されます。Visual Studio ソリューションのリビルドを実行し、
PetShopRestClient
フォルダーに生成されたクライアントを確認します。次に、生成されたクライアントを使用します。 クライアント Program.csに移動し、次のコードをコピーします。
using System; using System.Net.Http; namespace PetReaderExecTaskExample { internal class Program { private const string baseUrl = "https://petstore.swagger.io/v2"; static void Main(string[] args) { HttpClient httpClient = new HttpClient(); httpClient.BaseAddress = new Uri(baseUrl); var petClient = new PetShopRestClient.PetShopRestClient(httpClient); var pet = petClient.GetPetByIdAsync(1).Result; Console.WriteLine($"Id: {pet.Id} Name: {pet.Name} Status: {pet.Status} CategoryName: {pet.Category.Name}"); } } }
手記
このコードでは
new HttpClient()
を使用します。これは簡単に示すのですが、実際のコードではベスト プラクティスではありません。 ベスト プラクティスは、HttpClientFactory
を使用して、リソース不足や古い DNS の問題など、HttpClient
要求の既知の問題に対処するHttpClient
オブジェクトを作成することです。 「IHttpClientFactory を使用して回復性の高い HTTP 要求を実装する」を参照してください。
おめでとうございます! これで、プログラムを実行して動作を確認できます。
オプション 2: ToolTask から派生したカスタム タスク
多くの場合、Exec
タスクを使用すると、外部ツールを実行して REST API クライアント コードの生成などを行うことができますが、絶対 Windows パスを入力として使用しない場合にのみ、REST API クライアント コードの生成を許可する場合はどうすればよいでしょうか。 または、実行可能ファイルがある場所で何らかの方法で計算する必要がある場合はどうなりますか? 余分な作業を行うために何らかのコードを実行する必要がある状況がある場合は、MSBuild ツール タスク が最適なソリューションです。 ToolTask
クラスは、MSBuild Task
から派生した抽象クラスです。 カスタム MSBuild タスクを作成する具象サブクラスを定義できます。 この方法では、コマンド実行の準備に必要なコードを実行できます。 最初に、コード生成 用のカスタム タスクを作成する チュートリアルを読む必要があります。
REST API クライアントを生成 MSBuild ToolTask から派生したカスタム タスクを作成しますが、http アドレスを使用して OpenAPI 仕様を参照しようとするとエラーが生成されるように設計されています。 NSwag では OpenAPI 仕様の入力として http アドレスがサポートされていますが、この例では、これを禁止する設計要件があるとします。
完全なコードは、この PetReaderToolTaskExample
フォルダーにあります。ダウンロードして見ることができます。 このチュートリアルでは、段階的に説明し、独自のシナリオに適用できるいくつかの概念について説明します。
カスタム タスク用の新しい Visual Studio プロジェクトを作成します。
RestApiClientGenerator
呼び出し、.NET Standard 2.0 で クラス ライブラリ (C#) テンプレートを使用します。 ソリューションにPetReaderToolTaskExample
名前を付けます。自動的に生成された Class1.csを削除します。
Microsoft.Build.Utilities.Core
NuGet パッケージを追加します。RestApiClientGenerator
というクラスを作成するMSBuild
ToolTask
から継承し、次のコードに示すように抽象メソッドを実装します。using Microsoft.Build.Utilities; namespace RestApiClientGenerator { public class RestApiClientGenerator : ToolTask { protected override string ToolName => throw new System.NotImplementedException(); protected override string GenerateFullPathToTool() { throw new System.NotImplementedException(); } } }
次のパラメーターを追加します。
- InputOpenApiSpec: 仕様がある場所
- ClientClassName、生成されたクラスの名前
- ClientNamespaceName、クラスが生成される名前空間
- FolderClientClass、クラスが配置されるフォルダーへのパス
- NSwagCommandFullPath、NSwag.exe が配置されているディレクトリへの完全なパス
[Required] public string InputOpenApiSpec { get; set; } [Required] public string ClientClassName { get; set; } [Required] public string ClientNamespaceName { get; set; } [Required] public string FolderClientClass { get; set; } [Required] public string NSwagCommandFullPath { get; set; }
NSwag コマンド ライン ツール インストールします。 NSwag.exe が配置されているディレクトリへの完全なパスが必要です。
抽象メソッドを実装します。
protected override string ToolName => "RestApiClientGenerator"; protected override string GenerateFullPathToTool() { return $"{NSwagCommandFullPath}\\NSwag.exe"; }
オーバーライドできるメソッドは多数あります。 現在の実装では、次の 2 つを定義します。
- コマンド パラメーターを定義します。
protected override string GenerateCommandLineCommands() { return $"openapi2csclient /input:{InputOpenApiSpec} /classname:{ClientClassName} /namespace:{ClientNamespaceName} /output:{FolderClientClass}\\{ClientClassName}.cs"; }
- パラメーターの検証:
protected override bool ValidateParameters() { //http address is not allowed var valid = true; if (InputOpenApiSpec.StartsWith("http:") || InputOpenApiSpec.StartsWith("https:")) { valid = false; Log.LogError("URL is not allowed"); } return valid; }
手記
この単純な検証は MSBuild ファイルで他の方法で行うことができますが、C# コードで実行し、コマンドとロジックをカプセル化することをお勧めします。
プロジェクトをビルドします。
新しい MSBuild タスクを使用するコンソール アプリを作成する
次の手順では、タスクを使用するアプリを作成します。
コンソール アプリ プロジェクトを作成し、それを
PetReaderToolTaskConsoleApp
呼び出します。 .NET 6.0 を選択します。 スタートアップ プロジェクトとしてマークします。PetRestApiClient
と呼ばれるコードを生成する クラス ライブラリ プロジェクトを作成します。 .NET Standard 2.1 を使用します。PetReaderToolTaskConsoleApp
プロジェクトにおいて、PetRestApiClient
プロジェクトへの依存関係を作成します。PetRestApiClient
プロジェクトで、PetRestApiClient
フォルダーを作成します。 このフォルダーには、生成されたコードが含まれます。自動的に生成された Class1.csを削除します。
PetRestApiClient
で、次の NuGet パッケージを追加します。- 生成されたクライアントをコンパイルするために必要な Newtonsoft.Json
- 生成されたクライアントをコンパイルするために必要な System.ComponentModel.Annotations
PetRestApiClient
プロジェクトで、(プロジェクト フォルダー内に) petshop-openapi-spec.json という名前のテキスト ファイルを作成します。 OpenAPI 仕様を追加するには、ここで からファイルにコンテンツをコピーします。 前に説明したように、入力のみに依存する再現可能なビルドが好きです。 この例では、ユーザーが OpenAPI 仕様の入力として URL を選択すると、ビルド エラーが発生します。重要
一般的な再構築は機能しません。
RestApiClientGenerator
.dll をコピーまたは削除できないことを示すエラーが表示されます。 これは、MBuild カスタム タスクを使用する同じビルド プロセスでビルドしようとしているためです。PetReaderToolTaskConsoleApp
選択し、そのプロジェクトのみをリビルドします。 もう 1 つのソリューションは、「チュートリアル: カスタム タスクの作成 例」で行ったように、完全に独立した Visual Studio ソリューションにカスタム タスクを配置することです。次のコードを Program.csにコピーします。
using System; using System.Net.Http; namespace PetReaderToolTaskConsoleApp { internal class Program { private const string baseUrl = "https://petstore.swagger.io/v2"; static void Main(string[] args) { HttpClient httpClient = new HttpClient(); httpClient.BaseAddress = new Uri(baseUrl); var petClient = new PetRestApiClient.PetRestApiClient(httpClient); var pet = petClient.GetPetByIdAsync(1).Result; Console.WriteLine($"Id: {pet.Id} Name: {pet.Name} Status: {pet.Status} CategoryName: {pet.Category.Name}"); } } }
MSBuild 命令を変更してタスクを呼び出し、コードを生成します。 PetRestApiClient.csproj を次の手順に従って編集します。
MSBuild カスタム タスクの使用を登録します。
<UsingTask TaskName="RestApiClientGenerator.RestApiClientGenerator" AssemblyFile="..\RestApiClientGenerator\bin\Debug\netstandard2.0\RestApiClientGenerator.dll" />
タスクを実行するために必要なプロパティをいくつか追加します。
<PropertyGroup> <!--The place where the OpenAPI spec is in--> <PetClientInputOpenApiSpec>petshop-openapi-spec.json</PetClientInputOpenApiSpec> <PetClientClientClassName>PetRestApiClient</PetClientClientClassName> <PetClientClientNamespaceName>PetRestApiClient</PetClientClientNamespaceName> <PetClientFolderClientClass>PetRestApiClient</PetClientFolderClientClass> <!--The directory where NSawg.exe is in--> <NSwagCommandFullPath>C:\Nsawg\Win</NSwagCommandFullPath> </PropertyGroup>
重要
システム上のインストール場所に基づいて、適切な
NSwagCommandFullPath
値を選択します。MSBuild ターゲット を追加して、ビルド プロセス中にクライアントを生成します。 このターゲットは、コンパイルに使用するコードを生成するために、
CoreCompile
が実行される前に実行される必要があります。<Target Name="generatePetClient" BeforeTargets="CoreCompile" Inputs="$(PetClientInputOpenApiSpec)" Outputs="$(PetClientFolderClientClass)\$(PetClientClientClassName).cs"> <!--Calling our custom task derivated from MSBuild Tool Task--> <RestApiClientGenerator InputOpenApiSpec="$(PetClientInputOpenApiSpec)" ClientClassName="$(PetClientClientClassName)" ClientNamespaceName="$(PetClientClientNamespaceName)" FolderClientClass="$(PetClientFolderClientClass)" NSwagCommandFullPath="$(NSwagCommandFullPath)"></RestApiClientGenerator> </Target> <Target Name="forceReGenerationOnRebuild" AfterTargets="CoreClean"> <Delete Files="$(PetClientFolderClientClass)\$(PetClientClientClassName).cs"></Delete> </Target>
Input
とOutput
は インクリメンタル ビルドに関連しており、forceReGenerationOnRebuild
ターゲットはCoreClean
後に生成されたファイルを削除します。これによって、リビルド操作中にクライアントが強制的に再生成されます。PetReaderToolTaskConsoleApp
選択し、そのプロジェクトのみをリビルドします。 これで、クライアント コードが生成され、コードがコンパイルされます。 これを実行して、そのしくみを確認できます。 このコードはファイルからコードを生成し、許可されます。この手順では、パラメーターの検証を示します。 PetRestApiClient.csprojで、URL を使用するようにプロパティ
$(PetClientInputOpenApiSpec)
を変更します。<PetClientInputOpenApiSpec>https://petstore.swagger.io/v2/swagger.json</PetClientInputOpenApiSpec>
PetReaderToolTaskConsoleApp
選択し、そのプロジェクトのみをリビルドします。 デザイン要件に従って、"URL は許可されていません" というエラーが表示されます。
コードをダウンロードする
NSwag コマンド ライン ツールをインストールします。 次に、NSwag.exe が配置されているディレクトリへの完全なパスが必要になります。 その後、PetRestApiClient.csproj 編集し、コンピューター上のインストール パスに基づいて適切な $(NSwagCommandFullPath)
値を選択します。 次に、RestApiClientGenerator
を選択し、そのプロジェクトのみをビルドし、最後に PetReaderToolTaskConsoleApp
を選択して再構築します。 PetReaderToolTaskConsoleApp
を実行できます。 すべてが期待どおりに動作することを確認するために。
次の手順
カスタム タスクを NuGet パッケージとして発行することもできます。
チュートリアル: カスタム タスク を作成する
または、カスタム タスクをテストする方法について説明します。
カスタム MSBuild タスク をテストする