Freigeben über


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.

  1. Erstellen Sie eine neue Konsolenanwendung mit dem Namen PetReaderExecTaskExample. Verwenden Sie .NET 6.0 oder höher.

  2. 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.

  3. Fügen Sie im PetReaderExecTaskExample-Projekt eine Projektabhängigkeit zum PetShopRestClient-Projekt hinzu.

  4. 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
  5. Fügen Sie im PetShopRestClient Projekt einen Ordner (mit dem Namen PetShopRestClient) für die Codegenerierung hinzu, und löschen Sie die automatisch generierte Class1.cs.

  6. 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.

  7. Ä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 die Exec 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>-Tag ConsoleToMsBuild="true" hinzufügen und dann die Ausgabe mithilfe des ConsoleOutput-Parameters in einem <Output>-Tag erfassen. ConsoleOutput gibt die Ausgabe als Item zurück. Leerzeichen werden abgeschnitten. ConsoleOutput ist aktiviert, wenn ConsoleToMSBuild 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-Ziel CoreClean ausgeführt.

  8. Führen Sie einen Neuaufbau einer Visual Studio-Projektmappe durch, und sehen Sie den Client, der im Ordner PetShopRestClient generiert wurde.

  9. 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 eines HttpClient Objekts zu verwenden, das die bekannten Probleme HttpClient 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 Taskabgeleitet 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.

  1. 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ösung PetReaderToolTaskExample.

  2. Löschen Sie Class1.cs, die automatisch generiert wurde.

  3. 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();
              }
          }
      }
      
  4. 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; }
    
  5. Installieren Sie das NSwag-Befehlszeilentool. Sie benötigen den vollständigen Pfad zum Verzeichnis, in dem sich NSwag.exe befindet.

  6. Implementieren Sie die abstrakten Methoden:

       protected override string ToolName => "RestApiClientGenerator";
    
       protected override string GenerateFullPathToTool()
       {
           return $"{NSwagCommandFullPath}\\NSwag.exe";
       }
    
  7. 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.

  8. 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.

  1. Erstellen Sie ein Konsolen-App-Projekt, und nennen Sie es PetReaderToolTaskConsoleApp. Wählen Sie .NET 6.0 aus. Markieren Sie es als Startprojekt.

  2. Erstellen Sie ein Klassenbibliothek Projekt, um den Code zu generieren, der als PetRestApiClientbezeichnet wird. Verwenden Sie .NET Standard 2.1.

  3. Erstellen Sie im PetReaderToolTaskConsoleApp Projekt eine Projektabhängigkeit zum PetRestApiClient.

  4. Erstellen Sie im PetRestApiClient Projekt einen Ordner PetRestApiClient. Dieser Ordner enthält den generierten Code.

  5. Löschen Sie Class1.cs, die automatisch generiert wurde.

  6. Fügen Sie in PetRestApiClientdie folgenden NuGet-Pakete hinzu:

    • Newtonsoft.Json, erforderlich, um den generierten Client zu kompilieren
    • System.ComponentModel.Annotations, erforderlich, um den generierten Client zu kompilieren
  7. 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 Sie PetReaderToolTaskConsoleApp 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.

  8. 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}");
           }
       }
     }
    
  9. Ä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:

    1. Registrieren Sie die Verwendung der benutzerdefinierten MSBuild-Aufgabe:

      <UsingTask TaskName="RestApiClientGenerator.RestApiClientGenerator" AssemblyFile="..\RestApiClientGenerator\bin\Debug\netstandard2.0\RestApiClientGenerator.dll" />
      
    2. 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.

    3. 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 und Output sind mit inkrementellem Buildverknüpft, und das forceReGenerationOnRebuild Ziel löscht die generierte Datei nach CoreClean, was erfordert, dass der Client während des Neuerstellungsvorgangs neu generiert wird.

  10. 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.

  11. 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>
    
  12. 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 PetReaderToolTaskConsoleAppaus, 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.