Lernprogramm: Generieren eines REST-API-Clients
Eine Anwendung, die eine REST-API nutzt, ist ein sehr häufiges Szenario. In der Regel müssen Sie Clientcode generieren, den Ihre Anwendung zum Aufrufen der REST-API verwenden kann. In diesem Lernprogramm erfahren Sie, wie Sie den REST-API-Client während des Buildprozesses mithilfe von MSBuild automatisch generieren. Sie verwenden NSwag, ein Tool, das Clientcode für eine REST-API generiert.
Der vollständige Beispielcode ist unter REST-API-Clientgenerierung im .NET-Beispiel-Repository auf GitHub verfügbar.
Das Beispiel zeigt eine Konsolen-App, die die öffentliche Pet Store-APIverwendet, die eine OpenAPI-Spezifikationveröffentlicht.
Das Lernprogramm setzt grundlegende Kenntnisse von MSBuild-Begriffen wie Aufgaben, Zielen, Eigenschaften oder Laufzeiten voraus; informationen zum erforderlichen Hintergrund finden Sie im Artikel MSBuild Concepts.
Wenn Sie ein Befehlszeilentool als Teil eines Builds ausführen möchten, sind zwei Ansätze zu berücksichtigen. Eine besteht darin, die MSBuild-Exec-Aufgabezu verwenden, mit der Sie ein Befehlszeilentool ausführen und dessen Parameter angeben können. Die andere Methode besteht darin, eine benutzerdefinierte Aufgabe zu erstellen, die von ToolTaskabgeleitet wird, wodurch Sie eine größere Kontrolle erhalten.
Voraussetzungen
Sie sollten über ein Verständnis von MSBuild-Konzepten wie Aufgaben, Zielen und Eigenschaften verfügen. Weitere Informationen finden Sie unter MSBuild-Konzepte.
In den Beispielen ist MSBuild erforderlich, die mit Visual Studio installiert ist, aber auch separat installiert werden kann. Siehe Herunterladen von MSBuild ohne Visual Studio.
Option 1: Ausführungsaufgabe
Die Exec-Aufgabe einfach den angegebenen Prozess mit den angegebenen Argumenten aufruft, wartet auf den Abschluss, und gibt dann true
zurück, wenn der Prozess erfolgreich abgeschlossen ist, und false
, wenn ein Fehler auftritt.
Die NSwag-Codegenerierung kann von MSBuild verwendet werden; siehe NSwag.MSBuild.
Der vollständige Code befindet sich im ordner PetReaderExecTaskExample; Sie können herunterladen und einen Blick werfen. In diesem Tutorial werden Sie Schritt für Schritt den Ablauf durchgehen und die Konzepte unterwegs erlernen.
Erstellen Sie eine neue Konsolenanwendung mit dem Namen
PetReaderExecTaskExample
. Verwenden Sie .NET 6.0 oder höher.Erstellen Sie ein weiteres Projekt in derselben Lösung:
PetShopRestClient
(Diese Lösung wird den generierten Client als Bibliothek enthalten). Verwenden Sie für dieses Projekt .NET Standard 2.1. Der generierte Client kompiliert nicht auf .NET Standard 2.0.Fügen Sie im
PetReaderExecTaskExample
-Projekt eine Projektabhängigkeit zumPetShopRestClient
-Projekt hinzu.Schließen Sie im
PetShopRestClient
Projekt die folgenden NuGet-Pakete ein:- Nswag.MSBuild, das den Zugriff auf den Codegenerator von MSBuild ermöglicht
- Newtonsoft.Json, erforderlich, um den generierten Client zu kompilieren
- System.ComponentModel.Annotations, erforderlich, um den generierten Client zu kompilieren
Fügen Sie im
PetShopRestClient
Projekt einen Ordner (mit dem NamenPetShopRestClient
) für die Codegenerierung hinzu, und löschen Sie die automatisch generierte Class1.cs.Erstellen Sie eine Textdatei mit dem Namen petshop-openapi-spec.json im Stammverzeichnis des Projekts. Kopieren Sie die OpenAPI-Spezifikation aus hier, und speichern Sie sie in der Datei. Es ist am besten, eine Momentaufnahme der Spezifikation zu kopieren, anstatt sie während des Buildvorgangs online zu lesen. Sie möchten immer einen durchgängig reproduzierbaren Build, der nur von der Eingabe abhängt. Das direkte Verwenden der API könnte einen Build transformieren, der heute in einen Build funktioniert, der morgen von derselben Quelle aus fehlschlägt. Die auf petshop-openapi-spec.json gespeicherte Momentaufnahme ermöglicht es uns, weiterhin über eine Version zu verfügen, die erstellt wird, auch wenn sich die Spezifikation ändert.
Ändern Sie als Nächstes PetShopRestClient.csproj, und fügen Sie MSBuild targets hinzu, um den Client während des Buildprozesses zu generieren.
Fügen Sie zunächst einige Nützliche Eigenschaften für die Clientgenerierung hinzu:
<PropertyGroup> <PetOpenApiSpecLocation>petshop-openapi-spec.json</PetOpenApiSpecLocation> <PetClientClassName>PetShopRestClient</PetClientClassName> <PetClientNamespace>PetShopRestClient</PetClientNamespace> <PetClientOutputDirectory>PetShopRestClient</PetClientOutputDirectory> </PropertyGroup>
Fügen Sie die folgenden Ziele hinzu:
<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>
Beachten Sie, dass dieses Ziel die Attribute BeforeTarget- und AfterTarget- verwendet, um die Buildreihenfolge zu definieren. Das erste Ziel namens
generatePetClient
wird vor dem Kernkompilierungsziel ausgeführt, sodass die Quelle erstellt wird, bevor der Compiler ausgeführt wird. Die Eingabe- und Ausgabeparameter beziehen sich auf inkrementelle Builds. MSBuild kann die Zeitstempel der Eingabedateien mit den Zeitstempeln der Ausgabedateien vergleichen und bestimmen, ob ein Ziel übersprungen, erstellt oder teilweise neu erstellt werden soll.Nach der Installation des
NSwag.MSBuild
NuGet-Pakets in Ihrem Projekt können Sie die Variable$(NSwagExe)
in Ihrer.csproj
Datei verwenden, um das Befehlszeilentool NSwag in einem MSBuild-Ziel auszuführen. Auf diese Weise können die Tools einfach über NuGet aktualisiert werden. Hier verwenden Sie dieExec
MSBuild-Aufgabe, um das NSwag-Programm mit den erforderlichen Parametern auszuführen, um die Client-Rest-API zu generieren. Weitere Informationen finden Sie unter NSwag-Befehl und -Parameter.Sie können die Ausgabe aus
<Exec>
erfassen, indem Sie Ihrem<Exec>
-TagConsoleToMsBuild="true"
hinzufügen und dann die Ausgabe mithilfe desConsoleOutput
-Parameters in einem<Output>
-Tag erfassen.ConsoleOutput
gibt die Ausgabe alsItem
zurück. Leerzeichen werden abgeschnitten.ConsoleOutput
ist aktiviert, wennConsoleToMSBuild
wahr ist.Das zweite Ziel namens
forceReGenerationOnRebuild
löscht die generierte Klasse während der Bereinigung, um die Neugenerierung des Codes beim Ausführen des Neubauziels zu erzwingen. Dieses Ziel wird nach dem vordefinierten MSBuild-ZielCoreClean
ausgeführt.Führen Sie einen Neuaufbau einer Visual Studio-Projektmappe durch, und sehen Sie den Client, der im Ordner
PetShopRestClient
generiert wurde.Verwenden Sie nun den generierten Client. Wechseln Sie zum Client-Program.cs, und kopieren Sie den folgenden Code:
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}"); } } }
Anmerkung
Dieser Code verwendet
new HttpClient()
, da es einfach zu veranschaulichen ist, aber es ist nicht die bewährte Methode für realen Code. Die bewährte Methode besteht darin,HttpClientFactory
zum Erstellen einesHttpClient
Objekts zu verwenden, das die bekannten ProblemeHttpClient
Anforderung wie Ressourcenausschöpfung oder veraltete DNS-Probleme behandelt. Siehe Verwenden von IHttpClientFactory zum Implementieren widerstandsfähiger HTTP-Anforderungen.
Glückwunsch! Jetzt können Sie das Programm ausführen, um zu sehen, wie es funktioniert.
Option 2: Von ToolTask abgeleitete benutzerdefinierte Aufgabe
In vielen Fällen ist die Verwendung der aufgabe Exec
gut genug, um ein externes Tool auszuführen, um etwas wie die REST-API-Clientcodegenerierung auszuführen, aber was ist, wenn Sie die Generierung von REST-API-Clientcode nur dann zulassen möchten, wenn Sie keinen absoluten Windows-Pfad als Eingabe verwenden? Oder was geschieht, wenn Sie in irgendeiner Weise berechnen müssen, wo sich die ausführbare Datei befindet? Wenn es Situationen gibt, in denen Sie Code ausführen müssen, um zusätzliche Aufgaben auszuführen, ist die MSBuild Tool Task die beste Lösung. Die ToolTask
-Klasse ist eine abstrakte Klasse, die von MSBuild Task
abgeleitet wird. Sie können eine konkrete Unterklasse definieren, die eine benutzerdefinierte MSBuild-Aufgabe erstellt. Mit diesem Ansatz können Sie code ausführen, der zum Vorbereiten der Befehlsausführung erforderlich ist. Zuerst sollten Sie die Anleitung Erstellen einer benutzerdefinierten Aufgabe für die Codegenerierung lesen.
Sie erstellen eine benutzerdefinierte Aufgabe, die von MSBuild ToolTask abgeleitet wird, die einen REST-API-Client generiert, aber es wird so konzipiert, dass ein Fehler ausgegeben wird, wenn Sie versuchen, mithilfe einer HTTP-Adresse auf die OpenAPI-Spezifikation zu verweisen. NSwag unterstützt eine http-Adresse als OpenAPI-Spezifikation, aber für die Zwecke dieses Beispiels nehmen wir an, dass eine Entwurfsanforderung dies verbietet.
Der vollständige Code befindet sich in diesem PetReaderToolTaskExample
Ordner; Sie können herunterladen und einen Blick werfen. In diesem Lernprogramm werden Sie schrittweise durchgehen und einige Konzepte lernen, die Sie auf Ihre eigenen Szenarien anwenden können.
Erstellen Sie ein neues Visual Studio-Projekt für den benutzerdefinierten Vorgang. Rufen Sie es
RestApiClientGenerator
auf, und verwenden Sie die Klassenbibliothek (C#) Vorlage mit .NET Standard 2.0. Benennen Sie die LösungPetReaderToolTaskExample
.Löschen Sie Class1.cs, die automatisch generiert wurde.
Fügen Sie die
Microsoft.Build.Utilities.Core
NuGet-Pakete hinzu:Erstellen einer Klasse namens
RestApiClientGenerator
Leiten Sie von MSBuild
ToolTask
ab und implementieren Sie die abstrakte Methode, wie im folgenden Code gezeigt: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(); } } }
Fügen Sie die folgenden Parameter hinzu:
- InputOpenApiSpec: Speicherort der Spezifikation
- ClientClassName, Name der generierten Klasse
- ClientNamespaceName, Namespace, in dem die Klasse generiert wird
- FolderClientClass, Pfad zum Ordner, in dem sich die Klasse befindet
- NSwagCommandFullPath, vollständiger Pfad zum Verzeichnis, in dem sich NSwag.exe befindet
[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; }
Installieren Sie das NSwag-Befehlszeilentool. Sie benötigen den vollständigen Pfad zum Verzeichnis, in dem sich NSwag.exe befindet.
Implementieren Sie die abstrakten Methoden:
protected override string ToolName => "RestApiClientGenerator"; protected override string GenerateFullPathToTool() { return $"{NSwagCommandFullPath}\\NSwag.exe"; }
Es gibt viele Methoden, die Sie außer Kraft setzen können. Definieren Sie für die aktuelle Implementierung die folgenden beiden:
- Definieren Sie den Befehlsparameter:
protected override string GenerateCommandLineCommands() { return $"openapi2csclient /input:{InputOpenApiSpec} /classname:{ClientClassName} /namespace:{ClientNamespaceName} /output:{FolderClientClass}\\{ClientClassName}.cs"; }
- Parameterüberprüfung:
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; }
Anmerkung
Diese einfache Überprüfung kann in der MSBuild-Datei auf andere Weise durchgeführt werden, aber es wird empfohlen, sie im C#-Code auszuführen und den Befehl und die Logik zu kapseln.
Erstellen Sie das Projekt.
Erstellen einer Konsolen-App zur Verwendung der neuen MSBuild-Aufgabe
Der nächste Schritt besteht darin, eine App zu erstellen, die die Aufgabe verwendet.
Erstellen Sie ein Konsolen-App-Projekt, und nennen Sie es
PetReaderToolTaskConsoleApp
. Wählen Sie .NET 6.0 aus. Markieren Sie es als Startprojekt.Erstellen Sie ein Klassenbibliothek Projekt, um den Code zu generieren, der als
PetRestApiClient
bezeichnet wird. Verwenden Sie .NET Standard 2.1.Erstellen Sie im
PetReaderToolTaskConsoleApp
Projekt eine Projektabhängigkeit zumPetRestApiClient
.Erstellen Sie im
PetRestApiClient
Projekt einen OrdnerPetRestApiClient
. Dieser Ordner enthält den generierten Code.Löschen Sie Class1.cs, die automatisch generiert wurde.
Fügen Sie in
PetRestApiClient
die folgenden NuGet-Pakete hinzu:- Newtonsoft.Json, erforderlich, um den generierten Client zu kompilieren
- System.ComponentModel.Annotations, erforderlich, um den generierten Client zu kompilieren
Erstellen Sie im
PetRestApiClient
Projekt eine Textdatei namens petshop-openapi-spec.json (im Projektordner). Um die OpenAPI-Spezifikation hinzuzufügen, kopieren Sie den Inhalt aus hier in die Datei. Wir mögen einen reproduzierbaren Build, der nur von der Eingabe abhängt, wie zuvor beschrieben. In diesem Beispiel lösen Sie einen Buildfehler aus, wenn ein Benutzer eine URL als OpenAPI-Spezifikationseingabe auswählt.Wichtig
Ein allgemeiner Neuaufbau funktioniert nicht. Es werden Fehler angezeigt, die darauf hinweisen, dass sie
RestApiClientGenerator
.dllnicht kopieren oder löschen können. Dies liegt daran, dass sie versuchen, die benutzerdefinierte MBuild-Aufgabe im selben Buildprozess zu erstellen, der sie verwendet. Wählen SiePetReaderToolTaskConsoleApp
aus, und erstellen Sie nur das Projekt neu. Die andere Lösung besteht darin, die benutzerdefinierte Aufgabe in einer vollständig unabhängigen Visual Studio-Lösung zu platzieren, so wie im Beispiel im Tutorial: Erstellen einer benutzerdefinierten Aufgabe.Kopieren Sie den folgenden Code in 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}"); } } }
Ändern Sie die MSBuild-Anweisungen, um die Aufgabe aufzurufen und den Code zu generieren. Bearbeiten Sie PetRestApiClient.csproj, indem Sie die folgenden Schritte ausführen:
Registrieren Sie die Verwendung der benutzerdefinierten MSBuild-Aufgabe:
<UsingTask TaskName="RestApiClientGenerator.RestApiClientGenerator" AssemblyFile="..\RestApiClientGenerator\bin\Debug\netstandard2.0\RestApiClientGenerator.dll" />
Fügen Sie einige Eigenschaften hinzu, die zum Ausführen der Aufgabe erforderlich sind:
<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>
Wichtig
Wählen Sie den richtigen
NSwagCommandFullPath
-Wert basierend auf dem Installationsspeicherort in Ihrem System aus.Fügen Sie ein MSBuild-Ziel hinzu, um den Client während des Buildvorgangs zu generieren. Dieses Ziel sollte ausgeführt werden, bevor
CoreCompile
ausgeführt wird, um den in der Kompilierung verwendeten Code zu generieren.<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
undOutput
sind mit inkrementellem Buildverknüpft, und dasforceReGenerationOnRebuild
Ziel löscht die generierte Datei nachCoreClean
, was erfordert, dass der Client während des Neuerstellungsvorgangs neu generiert wird.Wählen Sie
PetReaderToolTaskConsoleApp
aus, und erstellen Sie nur das Projekt neu. Nun wird der Clientcode generiert und der Code kompiliert. Sie können es ausführen und sehen, wie es funktioniert. Dieser Code generiert den Code aus einer Datei und ist zulässig.In diesem Schritt veranschaulichen Sie die Parameterüberprüfung. Ändern Sie in PetRestApiClient.csprojdie Eigenschaft
$(PetClientInputOpenApiSpec)
, um die URL zu verwenden:<PetClientInputOpenApiSpec>https://petstore.swagger.io/v2/swagger.json</PetClientInputOpenApiSpec>
Wählen Sie
PetReaderToolTaskConsoleApp
aus, und erstellen Sie nur das Projekt neu. Sie erhalten die Fehlermeldung "URL ist nicht zulässig" gemäß der Entwurfsanforderung.
Code herunterladen
Installieren Sie das Befehlszeilentool NSwag. Anschließend benötigen Sie den vollständigen Pfad zum Verzeichnis, in dem sich NSwag.exe befindet. Bearbeiten Sie danach PetRestApiClient.csproj, und wählen Sie den richtigen $(NSwagCommandFullPath)
Wert basierend auf dem Installationspfad auf Ihrem Computer aus. Wählen Sie nun RestApiClientGenerator
aus, und erstellen Sie nur dieses Projekt, und wählen Sie schließlich PetReaderToolTaskConsoleApp
aus, und erstellen Sie es erneut. Sie können PetReaderToolTaskConsoleApp
ausführen. um sicherzustellen, dass alles wie erwartet funktioniert.
Nächste Schritte
Möglicherweise möchten Sie Ihre benutzerdefinierte Aufgabe als NuGet-Paket veröffentlichen.
Oder erfahren Sie, wie Sie eine benutzerdefinierte Aufgabe testen.