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 sezione generazione del client dell'API REST nel repository di esempi .NET su GitHub.
L'esempio mostra un'applicazione console che sfrutta l'API pubblica Pet Store, che pubblica una specifica OpenAPI .
L'esercitazione presuppone una conoscenza basilare dei termini di MSBuild, come attività, destinazioni, proprietà o runtime; per le 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 di 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: Esegui attività
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 dopo passo e si apprenderanno i concetti man mano.
Creare una nuova applicazione console denominata
PetReaderExecTaskExample
. Usare .NET 6.0 o versione successiva.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.Nel progetto
PetReaderExecTaskExample
, aggiungere una dipendenza dal progettoPetShopRestClient
.Nel progetto
PetShopRestClient
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
Nel progetto
PetShopRestClient
aggiungere una cartella (denominataPetShopRestClient
) per la generazione del codice ed eliminare il Class1.cs generato automaticamente.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 memorizzato in petshop-openapi-spec.json ci consentirà di avere ancora una versione che si compila anche se la specifica cambia.
Successivamente, modifica PetShopRestClient.csproj e aggiungi un target 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 denominata
generatePetClient
verrà eseguita prima della destinazione di compilazione principale, quindi l'origine verrà creata prima dell'esecuzione del compilatore. I parametri di ingresso e uscita sono correlati 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 pacchetto NuGet
NSwag.MSBuild
nel progetto, è possibile usare la variabile$(NSwagExe)
nel file.csproj
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. Consultare il comando NSwag e i relativi parametri .È possibile acquisire l'output da
<Exec>
aggiungendoConsoleToMsBuild="true"
al tag<Exec>
e quindi acquisendo l'output usando il parametroConsoleOutput
in un tag<Output>
.ConsoleOutput
restituisce l'output comeItem
. Lo spazio vuoto viene tagliato.ConsoleOutput
è abilitato quandoConsoleToMSBuild
è vero.La seconda destinazione denominata
forceReGenerationOnRebuild
elimina la classe generata durante la pulizia per forzare la rigenerazione del codice generato durante l'esecuzione della destinazione di ricompilazione. Questa destinazione viene eseguita dopo la destinazione predefinitaCoreClean
di MSBuild.Eseguire una ricompilazione della soluzione di Visual Studio e visualizzare il client generato nella cartella
PetShopRestClient
.Usare ora il client generato. Passare al client Program.cse 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'usareHttpClientFactory
per creare un oggettoHttpClient
che risolve i problemi noti diHttpClient
richiesta, ad esempio problemi di esaurimento delle risorse o DNS non aggiornati. Consultare Usare IHttpClientFactory per l'implementazione di richieste HTTP affidabili.
Felicitazioni! È 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 si verifica una situazione in cui è necessario eseguire codice per eseguire operazioni aggiuntive, l'attività dello strumento MSBuild è la soluzione migliore. La classe ToolTask
è 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. Dovresti leggere prima l'esercitazione Creare 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 per la specifica OpenAPI, ma per i fini di questo esempio, supponiamo che ci sia un requisito di progettazione che vieti questo.
Il codice completo si trova in questa cartella PetReaderToolTaskExample
; è possibile scaricare e dare un'occhiata. In questa esercitazione verranno illustrati in dettaglio alcuni concetti che è possibile applicare ai propri scenari.
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 nomePetReaderToolTaskExample
.Eliminare Class1.cs, generato automaticamente.
Aggiungere i pacchetti NuGet
Microsoft.Build.Utilities.Core
: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(); } } }
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; }
Installare strumento da riga di comando NSwag. Ti servirà il percorso completo della directory in cui si trova NSwag.exe.
Implementare i metodi astratti:
protected override string ToolName => "RestApiClientGenerator"; protected override string GenerateFullPathToTool() { return $"{NSwagCommandFullPath}\\NSwag.exe"; }
Esistono molti metodi che è possibile sovrascrivere. 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.
Costruisci il progetto.
Creare un'app console per usare la nuova attività MSBuild
Il passaggio successivo consiste nel creare un'app che usa l'attività.
Creare un progetto di applicazione console e chiamarlo
PetReaderToolTaskConsoleApp
. Scegliere .NET 6.0. Contrassegnarlo come progetto di avvio.Creare un progetto di libreria di classi per generare il codice, denominato
PetRestApiClient
. Usare .NET Standard 2.1.Nel progetto
PetReaderToolTaskConsoleApp
creare una dipendenza del progetto perPetRestApiClient
.Nel progetto
PetRestApiClient
creare una cartellaPetRestApiClient
. Questa cartella conterrà il codice generato.Eliminare Class1.cs, generato automaticamente.
In
PetRestApiClient
aggiungere i pacchetti NuGet seguenti:- Newtonsoft.Json, necessario per compilare il client generato
- System.ComponentModel.Annotations, necessario per compilare il client generato
Nel progetto
PetRestApiClient
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. Ci piace una compilazione riproducibile che dipende solo dall'input, come discusso 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 costruire l'attività personalizzata MBuild nello stesso processo di compilazione che lo utilizza. SelezionarePetReaderToolTaskConsoleApp
e ricompilare solo quel progetto. L'altra soluzione consiste nell'inserire l'attività personalizzata in una soluzione di Visual Studio completamente indipendente, come hai fatto nell'esempio : esercitazione: Creare un'attività personalizzata nell'esempio.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}"); } } }
Modificare le istruzioni di MSBuild per chiamare l'attività e generare il codice. Modificare PetRestApiClient.csproj seguendo questa procedura:
Registrare l'uso dell'attività personalizzata MSBuild:
<UsingTask TaskName="RestApiClientGenerator.RestApiClientGenerator" AssemblyFile="..\RestApiClientGenerator\bin\Debug\netstandard2.0\RestApiClientGenerator.dll" />
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
NSwagCommandFullPath
appropriato in base alla posizione di installazione sul tuo sistema.Aggiungere un obiettivo MSBuild per generare il client durante il processo di compilazione. Questa destinazione deve essere eseguita prima dell'esecuzione di
CoreCompile
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
eOutput
sono correlati alla compilazione incrementale , e l'obiettivoforceReGenerationOnRebuild
elimina il file generato dopoCoreClean
, forzando la rigenerazione del client durante l'operazione di ricompilazione.Selezionare
PetReaderToolTaskConsoleApp
e ricompilare solo quel 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.In questo passaggio verrà illustrata la convalida dei parametri. In PetRestApiClient.csprojmodificare la proprietà
$(PetClientInputOpenApiSpec)
per usare l'URL:<PetClientInputOpenApiSpec>https://petstore.swagger.io/v2/swagger.json</PetClientInputOpenApiSpec>
Selezionare
PetReaderToolTaskConsoleApp
e ricompilare solo quel 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. Ti sarà quindi necessario il percorso completo della directory in cui si trova NSwag.exe. Successivamente, modificare PetRestApiClient.csproj e selezionare il valore $(NSwagCommandFullPath)
appropriato in base al percorso di installazione nel computer. Ora, selezionare RestApiClientGenerator
e compilare solo quel progetto, e infine selezionare e ricompilare PetReaderToolTaskConsoleApp
. È possibile eseguire PetReaderToolTaskConsoleApp
. per verificare che tutto funzioni come previsto.
Passaggi successivi
Potresti voler pubblicare la tua attività personalizzata come pacchetto NuGet.
Esercitazione : Creare un'attività personalizzata
In alternativa, informazioni su come testare un'attività personalizzata.