Samouczek: generowanie klienta interfejsu API REST

Aplikacja, która korzysta z interfejsu API REST, jest bardzo typowym scenariuszem. Zazwyczaj należy wygenerować kod klienta, którego aplikacja może używać do wywoływania interfejsu API REST. Z tego samouczka dowiesz się, jak automatycznie wygenerować klienta interfejsu API REST podczas procesu kompilacji przy użyciu programu MSBuild. Użyjesz narzędzia NSwag, które generuje kod klienta dla interfejsu API REST.

Kompletny przykładowy kod jest dostępny podczas generowania klienta interfejsu API REST w repozytorium przykładów platformy .NET w witrynie GitHub.

W przykładzie pokazano aplikację konsolową, która korzysta z publicznego interfejsu API sklepu Pet Store, który publikuje specyfikację interfejsu OpenAPI.

W tym samouczku założono podstawową wiedzę na temat terminów MSBuild, takich jak zadania, obiekty docelowe, właściwości lub środowiska uruchomieniowe; aby zapoznać się z niezbędnymi informacjami, zobacz artykuł MSBuild Concepts (Pojęcia dotyczące programu MSBuild).

Jeśli chcesz uruchomić narzędzie wiersza polecenia w ramach kompilacji, należy wziąć pod uwagę dwa podejścia. Jednym z nich jest użycie zadania MSBuild Exec, które umożliwia uruchomienie narzędzia wiersza polecenia i określenie jego parametrów. Druga metoda polega na utworzeniu niestandardowego zadania pochodzącego z narzędzia ToolTask, co zapewnia większą kontrolę.

Wymagania wstępne

Należy poznać pojęcia dotyczące programu MSBuild, takie jak zadania, obiekty docelowe i właściwości. Zobacz Pojęcia dotyczące programu MSBuild.

Przykłady wymagają programu MSBuild zainstalowanego w programie Visual Studio, ale można go również zainstalować oddzielnie. Zobacz Pobieranie programu MSBuild bez programu Visual Studio.

Opcja 1. Zadanie exec

Zadanie Exec po prostu wywołuje określony proces z określonymi argumentami, czeka na ukończenie, a następnie zwracatrue, jeśli proces zakończy się pomyślnie i false jeśli wystąpi błąd.

Generowanie kodu NSwag można używać z poziomu programu MSBuild; zobacz NSwag.MSBuild.

Kompletny kod znajduje się w folderze PetReaderExecTaskExample . Możesz pobrać i spojrzeć. W tym samouczku przejdziesz krok po kroku i poznasz pojęcia w drodze.

  1. Utwórz nową aplikację konsolową o nazwie PetReaderExecTaskExample. Użyj platformy .NET 6.0 lub nowszej.

  2. Utwórz inny projekt w tym samym rozwiązaniu: PetShopRestClient (To rozwiązanie będzie zawierać wygenerowanego klienta jako bibliotekę). W tym projekcie użyj platformy .NET Standard 2.1. Wygenerowany klient nie kompiluje się na platformie .NET Standard 2.0.

  3. W projekcie PetReaderExecTaskExample i dodaj zależność projektu do PetShopRestClient projektu.

  4. W projekcie PetShopRestClient uwzględnij następujące pakiety NuGet:

    • Nswag.MSBuild, który umożliwia dostęp do generatora kodu z programu MSBuild
    • Plik Newtonsoft.Json potrzebny do skompilowania wygenerowanego klienta
    • System.ComponentModel.Annotations— wymagane do skompilowania wygenerowanego klienta
  5. W projekcie PetShopRestClient dodaj folder (o nazwie PetShopRestClient) dla generowania kodu i usuń wygenerowany automatycznie plik Class1.cs .

  6. Utwórz plik tekstowy o nazwie petshop-openapi-spec.json w katalogu głównym projektu. Skopiuj specyfikację interfejsu OpenApi z tego miejsca i zapisz ją w pliku. Najlepiej skopiować migawkę specyfikacji zamiast odczytywać ją w trybie online podczas kompilacji. Zawsze potrzebujesz spójnej powtarzalnej kompilacji, która zależy tylko od danych wejściowych. Korzystanie z interfejsu API bezpośrednio może przekształcić kompilację, która działa dzisiaj w kompilacji, która kończy się niepowodzeniem jutro z tego samego źródła. Migawka zapisana w pliku petshop-openapi-spec.json pozwoli nam nadal mieć wersję, która kompiluje się nawet wtedy, gdy specyfikacja ulegnie zmianie.

  7. Następnie zmodyfikuj plik PetShopRestClient.csproj i dodaj elementy docelowe programu MSBuild, aby wygenerować klienta podczas procesu kompilacji.

    Najpierw dodaj kilka właściwości przydatnych do generowania klienta:

     <PropertyGroup>
         <PetOpenApiSpecLocation>petshop-openapi-spec.json</PetOpenApiSpecLocation>
         <PetClientClassName>PetShopRestClient</PetClientClassName>
         <PetClientNamespace>PetShopRestClient</PetClientNamespace>
         <PetClientOutputDirectory>PetShopRestClient</PetClientOutputDirectory>
     </PropertyGroup>
    

    Dodaj następujące elementy docelowe:

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

    Zwróć uwagę, że ten element docelowy używa atrybutów BeforeTarget i AfterTarget jako sposobu definiowania kolejności kompilacji. Pierwszy obiekt docelowy o nazwie generatePetClient zostanie wykonany przed elementem docelowym kompilacji podstawowej, więc źródło zostanie utworzone przed wykonaniem kompilatora. Parametr wejściowy i wyjściowy są powiązane z kompilacją przyrostową. Program MSBuild może porównać znaczniki czasu plików wejściowych ze znacznikami czasu plików wyjściowych i określić, czy pominąć, skompilować lub częściowo skompilować element docelowy.

    Po zainstalowaniu NSwag.MSBuild pakietu NuGet w projekcie możesz użyć zmiennej $(NSwagExe) w .csproj pliku, aby uruchomić narzędzie wiersza polecenia NSwag w obiekcie docelowym MSBuild. Dzięki temu narzędzia można łatwo aktualizować za pomocą narzędzia NuGet. W tym miejscu używasz Exec zadania MSBuild do wykonania programu NSwag z wymaganymi parametrami do wygenerowania interfejsu API REST klienta. Zobacz Polecenie i parametry sieciowej grupy zabezpieczeń.

    Możesz przechwycić dane wyjściowe z <Exec> dodawania ConsoleToMsBuild="true" do tagu <Exec> , a następnie przechwytywać dane wyjściowe przy użyciu parametru ConsoleOutput w tagu <Output> . ConsoleOutput zwraca dane wyjściowe jako Item. Białe znaki są przycinane. ConsoleOutput wartość jest włączona, gdy ConsoleToMSBuild ma wartość true.

    Drugi element docelowy o nazwie forceReGenerationOnRebuild usuwa wygenerowaną klasę podczas oczyszczania, aby wymusić ponowne wygenerowanie wygenerowanego kodu podczas ponownego kompilowania wykonania docelowego. Ten element docelowy jest uruchamiany po wstępnie zdefiniowanym CoreClean obiekcie docelowym programu MSBuild.

  8. Wykonaj ponowną kompilację rozwiązania programu Visual Studio i zobacz klienta wygenerowanego w folderze PetShopRestClient .

  9. Teraz użyj wygenerowanego klienta. Przejdź do pliku client Program.cs i skopiuj następujący kod:

    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}");
           }
       }
    }
    

    Uwaga

    Ten kod jest używany new HttpClient() , ponieważ jest prosty do zademonstrowania, ale nie jest to najlepsze rozwiązanie dla kodu w świecie rzeczywistym. Najlepszym rozwiązaniem HttpClient jest HttpClientFactory utworzenie obiektu, który rozwiązuje znane problemy z żądaniem, HttpClient takie jak wyczerpanie zasobów lub nieaktualne problemy z systemem DNS. Zobacz Implementowanie odpornych żądań HTTP za pomocą interfejsu IHttpClientFactory.

Gratulacje! Teraz możesz wykonać program, aby zobaczyć, jak to działa.

Opcja 2. Niestandardowe zadanie pochodzące z narzędzia ToolTask

W wielu przypadkach użycie Exec zadania jest wystarczająco dobre, aby wykonać narzędzie zewnętrzne w celu wykonania czegoś takiego jak generowanie kodu klienta interfejsu API REST, ale co zrobić, jeśli chcesz zezwolić na generowanie kodu klienta interfejsu API REST, jeśli i tylko wtedy, gdy nie używasz bezwzględnej ścieżki systemu Windows jako danych wejściowych? A co zrobić, jeśli chcesz obliczyć w jakiś sposób, gdzie znajduje się plik wykonywalny? Jeśli istnieje sytuacja, w której trzeba wykonać jakiś kod, aby wykonać dodatkową pracę, zadanie narzędzia MSBuild jest najlepszym rozwiązaniem. Klasa ToolTask jest abstrakcyjną klasą pochodzącą z MSBuild Task. Można zdefiniować konkretną podklasę, która tworzy niestandardowe zadanie MSBuild. Takie podejście umożliwia uruchomienie dowolnego kodu potrzebnego do przygotowania do wykonania polecenia. Przeczytaj samouczek Tworzenie niestandardowego zadania dla pierwszej generacji kodu.

Utworzysz zadanie niestandardowe pochodzące z narzędzia MSBuild ToolTask , które wygeneruje klienta interfejsu API REST, ale zostanie zaprojektowane tak, aby emitować błąd, jeśli spróbujesz odwołać się do specyfikacji interfejsu OpenApi przy użyciu adresu HTTP. NSwag obsługuje adres HTTP jako dane wejściowe specyfikacji OpenApi, ale na potrzeby tego przykładu załóżmy, że istnieje wymaganie projektowe, aby tego nie zezwalać.

Kompletny kod znajduje się w tym PetReaderToolTaskExample folderze. Możesz pobrać i spojrzeć. W tym samouczku przejdziesz krok po kroku i poznasz pewne pojęcia, które można zastosować do własnych scenariuszy.

  1. Utwórz nowy projekt programu Visual Studio dla zadania niestandardowego. Wywołaj go RestApiClientGenerator i użyj szablonu Biblioteka klas (C#) z platformą .NET Standard 2.0. Nadaj rozwiązaniu PetReaderToolTaskExamplenazwę .

  2. Usuń plik Class1.cs, który został wygenerowany automatycznie.

  3. Microsoft.Build.Utilities.Core Dodaj pakiety NuGet:

    • Tworzenie klasy o nazwie RestApiClientGenerator

    • Dziedzicz z programu MSBuild ToolTask i zaimplementuj metodę abstrakcyjną, jak pokazano w poniższym kodzie:

      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. Dodaj następujące parametry:

    • InputOpenApiSpec, gdzie specyfikacją jest
    • ClientClassName, nazwa wygenerowanej klasy
    • ClientNamespaceName, przestrzeń nazw, w której jest generowana klasa
    • FolderClientClass, ścieżka do folderu, w którym będzie znajdować się klasa
    • NSwagCommandFullPath, pełna ścieżka do katalogu, w którym znajduje się plik 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; }
    
  5. Zainstaluj narzędzie wiersza polecenia NSwag. Będzie potrzebna pełna ścieżka do katalogu, w którym znajduje się plik NSwag.exe.

  6. Zaimplementuj metody abstrakcyjne:

       protected override string ToolName => "RestApiClientGenerator";
    
       protected override string GenerateFullPathToTool()
       {
           return $"{NSwagCommandFullPath}\\NSwag.exe";
       }
    
  7. Istnieje wiele metod, które można zastąpić. Dla bieżącej implementacji zdefiniuj następujące dwa:

    • Zdefiniuj parametr polecenia:
      protected override string GenerateCommandLineCommands()
      {
          return $"openapi2csclient /input:{InputOpenApiSpec}  /classname:{ClientClassName} /namespace:{ClientNamespaceName} /output:{FolderClientClass}\\{ClientClassName}.cs";
      }
    
    • Walidacja parametru:
    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;
    }
    

    Uwaga

    Tę prostą walidację można wykonać w inny sposób w pliku MSBuild, ale zaleca się wykonanie tej czynności w kodzie języka C# i hermetyzowanie polecenia i logiki.

  8. Skompiluj projekt.

Tworzenie aplikacji konsolowej do korzystania z nowego zadania MSBuild

Następnym krokiem jest utworzenie aplikacji korzystającej z zadania.

  1. Utwórz projekt aplikacja konsolowa i wywołaj go PetReaderToolTaskConsoleApp. Wybierz pozycję .NET 6.0. Oznacz go jako projekt startowy.

  2. Utwórz projekt Biblioteka klas w celu wygenerowania kodu o nazwie PetRestApiClient. Użyj platformy .NET Standard 2.1.

  3. W projekcie PetReaderToolTaskConsoleApp utwórz zależność projektu do PetRestApiClient.

  4. W projekcie PetRestApiClient utwórz folder PetRestApiClient. Ten folder będzie zawierać wygenerowany kod.

  5. Usuń plik Class1.cs, który został wygenerowany automatycznie.

  6. W pliku PetRestApiClientdodaj następujące pakiety NuGet:

    • Plik Newtonsoft.Json potrzebny do skompilowania wygenerowanego klienta
    • System.ComponentModel.Annotations— wymagane do skompilowania wygenerowanego klienta
  7. W projekcie PetRestApiClient utwórz plik tekstowy o nazwie petshop-openapi-spec.json (w folderze projektu). Aby dodać specyfikację interfejsu OpenApi, skopiuj zawartość z tego miejsca do pliku. Lubimy powtarzalną kompilację, która zależy tylko od danych wejściowych, jak wspomniano wcześniej. W tym przykładzie wystąpi błąd kompilacji, jeśli użytkownik wybierze adres URL jako dane wejściowe specyfikacji interfejsu OpenApi.

    Ważne

    Ogólna ponowna kompilacja nie będzie działać. Zobaczysz błędy wskazujące, że nie można skopiować ani usunąć RestApiClientGeneratorbiblioteki DLL. Jest to spowodowane tym, że próbuje skompilować zadanie niestandardowe MBuild w tym samym procesie kompilacji, który go używa. Wybierz PetReaderToolTaskConsoleApp i skompiluj tylko ten projekt. Innym rozwiązaniem jest umieszczenie zadania niestandardowego w całkowicie niezależnym rozwiązaniu programu Visual Studio, tak jak w artykule Samouczek: tworzenie niestandardowego przykładu zadania .

  8. Skopiuj następujący kod do pliku 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. Zmień instrukcje programu MSBuild, aby wywołać zadanie i wygenerować kod. Edytuj plik PetRestApiClient.csproj , wykonując następujące kroki:

    1. Zarejestruj użycie niestandardowego zadania MSBuild:

      <UsingTask TaskName="RestApiClientGenerator.RestApiClientGenerator" AssemblyFile="..\RestApiClientGenerator\bin\Debug\netstandard2.0\RestApiClientGenerator.dll" />
      
    2. Dodaj kilka właściwości potrzebnych do wykonania zadania:

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

      Ważne

      Wybierz odpowiednią NSwagCommandFullPath wartość na podstawie lokalizacji instalacji w systemie.

    3. Dodaj docelowy program MSBuild, aby wygenerować klienta podczas procesu kompilacji. Ten element docelowy powinien zostać wykonany przed CoreCompile wykonaniem w celu wygenerowania kodu użytego w kompilacji.

      <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 i Output są powiązane z kompilacją przyrostową, aforceReGenerationOnRebuild element docelowy usuwa wygenerowany plik po CoreClean, co wymusza ponowne wygenerowanie klienta podczas operacji ponownego kompilowania.

  10. Wybierz PetReaderToolTaskConsoleApp i skompiluj tylko ten projekt. Teraz kod klienta jest generowany, a kod jest kompilowany. Można go wykonać i zobaczyć, jak działa. Ten kod generuje kod z pliku i jest dozwolony.

  11. W tym kroku przedstawisz walidację parametru. W pliku PetRestApiClient.csproj zmień właściwość $(PetClientInputOpenApiSpec) tak, aby korzystała z adresu URL:

      <PetClientInputOpenApiSpec>https://petstore.swagger.io/v2/swagger.json</PetClientInputOpenApiSpec>
    
  12. Wybierz PetReaderToolTaskConsoleApp i skompiluj tylko ten projekt. Zostanie wyświetlony błąd "Adres URL jest niedozwolony" zgodnie z wymaganiami projektowymi.

Pobieranie kodu

Zainstaluj narzędzie wiersza polecenia NSwag. Następnie będziesz potrzebować pełnej ścieżki do katalogu, w którym znajduje się plik NSwag.exe. Następnie zmodyfikuj plik PetRestApiClient.csproj i wybierz odpowiednią $(NSwagCommandFullPath) wartość na podstawie ścieżki instalacji na komputerze. Teraz wybierz RestApiClientGenerator i skompiluj tylko ten projekt, a na koniec wybierz i ponownie skompiluj PetReaderToolTaskConsoleApp. Można wykonać polecenie PetReaderToolTaskConsoleApp. aby sprawdzić, czy wszystko działa zgodnie z oczekiwaniami.

Następne kroki

Możesz opublikować zadanie niestandardowe jako pakiet NuGet.

Możesz też dowiedzieć się, jak przetestować zadanie niestandardowe.