Esercitazione: Generare un client API REST

Un'applicazione che usa un'API REST è uno scenario molto comune. In genere, è necessario generare codice client che l'applicazione può usare per chiamare l'API REST. In questa esercitazione si apprenderà come generare automaticamente il client API REST durante il processo di compilazione usando MSBuild. Si userà NSwag, uno strumento che genera codice client per un'API REST.

Il codice di esempio completo è disponibile nella generazione del client DELL'API REST nel repository di esempi .NET in GitHub.

L'esempio mostra un'app console che usa l'API pubblica di Pet Store, che pubblica una specifica OpenAPI.

L'esercitazione presuppone una conoscenza di base dei termini di MSBuild, ad esempio attività, destinazioni, proprietà o runtime; per informazioni generali necessarie, vedere l'articolo Concetti relativi a MSBuild.

Quando si vuole eseguire uno strumento da riga di comando come parte di una compilazione, esistono due approcci da considerare. Uno consiste nell'usare l'attività MSBuild Exec, che consente di eseguire uno strumento da riga di comando e specificare i relativi parametri. L'altro metodo consiste nel creare un'attività personalizzata derivata da ToolTask, che offre un maggiore controllo.

Prerequisiti

È necessario avere una conoscenza dei concetti di MSBuild, ad esempio attività, destinazioni e proprietà. Vedere Concetti relativi a MSBuild.

Gli esempi richiedono MSBuild, installato con Visual Studio, ma possono anche essere installati separatamente. Vedere Scaricare MSBuild senza Visual Studio.

Opzione 1: Attività Exec

L'attività Exec richiama semplicemente il processo specificato con gli argomenti specificati, attende il completamento e quindi restituisce true se il processo viene completato correttamente e false se si verifica un errore.

La generazione di codice NSwag può essere usata da MSBuild; vedere NSwag.MSBuild.

Il codice completo si trova nella cartella PetReaderExecTaskExample . È possibile scaricare e dare un'occhiata. In questa esercitazione si esamineranno passo passo e si apprenderà i concetti sul percorso.

  1. Creare una nuova applicazione console denominata PetReaderExecTaskExample. Usare .NET 6.0 o versione successiva.

  2. Creare un altro progetto nella stessa soluzione: PetShopRestClient questa soluzione conterrà il client generato come libreria. Per questo progetto, usare .NET Standard 2.1. Il client generato non viene compilato in .NET Standard 2.0.

  3. PetReaderExecTaskExample Nel progetto e aggiungere una dipendenza del progetto al PetShopRestClient progetto.

  4. PetShopRestClient Nel progetto includere i pacchetti NuGet seguenti:

    • Nswag.MSBuild, che consente l'accesso al generatore di codice da MSBuild
    • Newtonsoft.Json, necessario per compilare il client generato
    • System.ComponentModel.Annotations, necessario per compilare il client generato
  5. PetShopRestClient Nel progetto aggiungere una cartella (denominata PetShopRestClient) per la generazione del codice ed eliminare il file Class1.cs generato automaticamente.

  6. Creare un file di testo denominato petshop-openapi-spec.json nella radice del progetto. Copiare la specifica OpenApi da qui e salvarla nel file. È consigliabile copiare uno snapshot della specifica invece di leggerlo online durante la compilazione. Si vuole sempre una compilazione riproducibile coerente che dipende solo dall'input. L'uso diretto dell'API potrebbe trasformare una compilazione che funziona oggi in una compilazione che ha esito negativo domani dalla stessa origine. Lo snapshot salvato in petshop-openapi-spec.json consentirà di avere ancora una versione compilata anche se la specifica cambia.

  7. Modificare quindi PetShopRestClient.csproj e aggiungere destinazioni MSBuild per generare il client durante il processo di compilazione.

    Aggiungere prima di tutto alcune proprietà utili per la generazione del client:

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

    Aggiungere le destinazioni seguenti:

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

    Si noti che questa destinazione usa gli attributi BeforeTarget e AfterTarget come modo per definire l'ordine di compilazione. La prima destinazione chiamata generatePetClient verrà eseguita prima della destinazione di compilazione principale, quindi l'origine verrà creata prima dell'esecuzione del compilatore. Il parametro di input e output è correlato alla compilazione incrementale. MSBuild può confrontare i timestamp dei file di input con i timestamp dei file di output e determinare se ignorare, compilare o ricompilare parzialmente una destinazione.

    Dopo aver installato il NSwag.MSBuild pacchetto NuGet nel progetto, è possibile usare la variabile $(NSwagExe) nel .csproj file per eseguire lo strumento da riga di comando NSwag in una destinazione MSBuild. In questo modo, gli strumenti possono essere facilmente aggiornati tramite NuGet. In questo caso si usa l'attività Exec MSBuild per eseguire il programma NSwag con i parametri necessari per generare l'API REST del client. Vedere Comandi e parametri NSwag.

    È possibile acquisire l'output dall'aggiunta <Exec>ConsoleToMsBuild="true" al <Exec> tag e quindi acquisire l'output usando il ConsoleOutput parametro in un <Output> tag. ConsoleOutputrestituisce l'output come .Item Lo spazio vuoto viene tagliato. ConsoleOutput è abilitato quando ConsoleToMSBuild è true.

    La seconda destinazione denominata forceReGenerationOnRebuild elimina la classe generata durante la pulizia per forzare la rigenerazione del codice generato durante l'esecuzione della ricompilazione della destinazione. Questa destinazione viene eseguita dopo la CoreClean destinazione predefinita di MSBuild.

  8. Eseguire una ricompilazione della soluzione di Visual Studio e visualizzare il client generato nella PetShopRestClient cartella .

  9. Usare ora il client generato. Passare al client Program.cs e copiare il codice seguente:

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

    Nota

    Questo codice usa new HttpClient() perché è semplice da dimostrare, ma non è la procedura consigliata per il codice reale. La procedura consigliata consiste nell'usare HttpClientFactory per creare un HttpClient oggetto che risolve i problemi noti della HttpClient richiesta, ad esempio esaurimento risorse o problemi DNS non aggiornati. Vedere Usare IHttpClientFactory per implementare richieste HTTP resilienti.

Si è così È ora possibile eseguire il programma per vedere come funziona.

Opzione 2: attività personalizzata derivata da ToolTask

In molti casi, l'uso dell'attività Exec è sufficiente per eseguire uno strumento esterno per eseguire operazioni come la generazione di codice client dell'API REST, ma cosa accade se si vuole consentire la generazione del codice client dell'API REST se e solo se non si usa un percorso di Windows assoluto come input? O se è necessario calcolare in qualche modo dove si trova l'eseguibile? Quando c'è una situazione in cui è necessario eseguire codice per eseguire operazioni aggiuntive, l'attività strumento MSBuild è la soluzione migliore. La ToolTask classe è una classe astratta derivata da MSBuild Task. È possibile definire una sottoclasse concreta, che crea un'attività MSBuild personalizzata. Questo approccio consente di eseguire qualsiasi codice necessario per preparare l'esecuzione dei comandi. Leggere l'esercitazione Creare prima un'attività personalizzata per la generazione di codice.

Si creerà un'attività personalizzata derivata da MSBuild ToolTask che genererà un client API REST, ma sarà progettata per generare un errore se si tenta di fare riferimento alla specifica OpenApi usando un indirizzo HTTP. NSwag supporta un indirizzo HTTP come input della specifica OpenApi, ma ai fini di questo esempio si supponga di non consentire un requisito di progettazione.

Il codice completo si trova in questa PetReaderToolTaskExample cartella. È possibile scaricare e dare un'occhiata. In questa esercitazione verranno illustrati in dettaglio alcuni concetti che è possibile applicare ai propri scenari.

  1. Creare un nuovo progetto di Visual Studio per l'attività personalizzata. Chiamarlo RestApiClientGenerator e usare il modello Libreria di classi (C#) con .NET Standard 2.0. Assegnare alla soluzione il nome PetReaderToolTaskExample.

  2. Eliminare Class1.cs, generato automaticamente.

  3. Aggiungere i Microsoft.Build.Utilities.Core pacchetti NuGet:

    • Creare una classe denominata RestApiClientGenerator

    • Ereditare da MSBuild ToolTask e implementare il metodo astratto come illustrato nel codice seguente:

      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. Aggiungere i parametri seguenti:

    • InputOpenApiSpec, dove la specifica è
    • ClientClassName, nome della classe generata
    • ClientNamespaceName, spazio dei nomi in cui viene generata la classe
    • FolderClientClass, percorso della cartella in cui si trova la classe
    • NSwagCommandFullPath, percorso completo della directory in cui si trova 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. Installare lo strumento da riga di comando NSwag. Sarà necessario il percorso completo della directory in cui si trova NSwag.exe.

  6. Implementare i metodi astratti:

       protected override string ToolName => "RestApiClientGenerator";
    
       protected override string GenerateFullPathToTool()
       {
           return $"{NSwagCommandFullPath}\\NSwag.exe";
       }
    
  7. Esistono molti metodi che è possibile eseguire l'override. Per l'implementazione corrente, definire questi due elementi:

    • Definire il parametro del comando:
      protected override string GenerateCommandLineCommands()
      {
          return $"openapi2csclient /input:{InputOpenApiSpec}  /classname:{ClientClassName} /namespace:{ClientNamespaceName} /output:{FolderClientClass}\\{ClientClassName}.cs";
      }
    
    • Convalida dei parametri:
    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;
    }
    

    Nota

    Questa semplice convalida può essere eseguita in altro modo nel file MSBuild, ma è consigliabile eseguirla nel codice C# e incapsulare il comando e la logica.

  8. Compilare il progetto.

Creare un'app console per usare la nuova attività MSBuild

Il passaggio successivo consiste nel creare un'app che usa l'attività.

  1. Creare un progetto app console e chiamarlo PetReaderToolTaskConsoleApp. Scegliere .NET 6.0. Contrassegnarlo come progetto di avvio.

  2. Creare un progetto libreria di classi per generare il codice denominato PetRestApiClient. Usare .NET Standard 2.1.

  3. PetReaderToolTaskConsoleApp Nel progetto creare una dipendenza del progetto da PetRestApiClient.

  4. PetRestApiClient Nel progetto creare una cartella PetRestApiClient. Questa cartella conterrà il codice generato.

  5. Eliminare Class1.cs, generato automaticamente.

  6. In PetRestApiClientaggiungere i pacchetti NuGet seguenti:

    • Newtonsoft.Json, necessario per compilare il client generato
    • System.ComponentModel.Annotations, necessario per compilare il client generato
  7. PetRestApiClient Nel progetto creare un file di testo denominato petshop-openapi-spec.json (nella cartella del progetto). Per aggiungere la specifica OpenApi, copiare il contenuto da qui nel file. È come una compilazione riproducibile che dipende solo dall'input, come illustrato in precedenza. In questo esempio verrà generato un errore di compilazione se un utente sceglie un URL come input della specifica OpenApi.

    Importante

    Una ricompilazione generale non funzionerà. Verranno visualizzati errori che indicano che non è possibile copiare o eliminare RestApiClientGenerator.dll'. Questo perché sta tentando di compilare l'attività personalizzata MBuild nello stesso processo di compilazione che lo usa. Selezionare PetReaderToolTaskConsoleApp e ricompilare solo il progetto. L'altra soluzione consiste nell'inserire l'attività personalizzata in una soluzione visual Studio completamente indipendente come illustrato in Esercitazione: Creare un esempio di attività personalizzata.

  8. Copiare il codice seguente 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. Modificare le istruzioni di MSBuild per chiamare l'attività e generare il codice. Modificare PetRestApiClient.csproj seguendo questa procedura:

    1. Registrare l'uso dell'attività personalizzata MSBuild:

      <UsingTask TaskName="RestApiClientGenerator.RestApiClientGenerator" AssemblyFile="..\RestApiClientGenerator\bin\Debug\netstandard2.0\RestApiClientGenerator.dll" />
      
    2. Aggiungere alcune proprietà necessarie per eseguire l'attività:

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

      Importante

      Selezionare il valore appropriato NSwagCommandFullPath in base al percorso di installazione nel sistema.

    3. Aggiungere una destinazione MSBuild per generare il client durante il processo di compilazione. Questa destinazione deve essere eseguita prima CoreCompile dell'esecuzione per generare il codice usato nella compilazione.

      <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 e Output sono correlati alla compilazione incrementale e laforceReGenerationOnRebuild destinazione elimina il file generato dopo CoreClean, che forza la rigenerazione del client durante l'operazione di ricompilazione.

  10. Selezionare PetReaderToolTaskConsoleApp e ricompilare solo il progetto. Il codice client viene ora generato e il codice viene compilato. È possibile eseguirlo e vedere come funziona. Questo codice genera il codice da un file e questo è consentito.

  11. In questo passaggio verrà illustrata la convalida dei parametri. In PetRestApiClient.csproj modificare la proprietà $(PetClientInputOpenApiSpec) in modo da usare l'URL:

      <PetClientInputOpenApiSpec>https://petstore.swagger.io/v2/swagger.json</PetClientInputOpenApiSpec>
    
  12. Selezionare PetReaderToolTaskConsoleApp e ricompilare solo il progetto. Verrà visualizzato l'errore "URL non consentito" in base ai requisiti di progettazione.

Scaricare il codice

Installare lo strumento da riga di comando NSwag. Sarà quindi necessario il percorso completo della directory in cui si trova NSwag.exe. Successivamente, modificare PetRestApiClient.csproj e selezionare il valore appropriato $(NSwagCommandFullPath) in base al percorso di installazione nel computer. Selezionare RestApiClientGenerator e compilare solo il progetto e infine selezionare e ricompilare PetReaderToolTaskConsoleApp. È possibile eseguire PetReaderToolTaskConsoleApp. per verificare che tutto funzioni come previsto.

Passaggi successivi

È possibile pubblicare l'attività personalizzata come pacchetto NuGet.

In alternativa, informazioni su come testare un'attività personalizzata.