Generare documenti OpenAPI
Il Microsoft.AspNetCore.OpenApi
pacchetto fornisce il supporto predefinito per la generazione di documenti OpenAPI in ASP.NET Core. Il pacchetto offre le funzionalità seguenti:
- Supporto per la generazione di documenti OpenAPI in fase di esecuzione e l'accesso tramite un endpoint nell'app.
- Supporto per le API "transformer" che consentono di modificare il documento generato.
- Supporto per la generazione di più documenti OpenAPI da una singola app.
- Sfrutta il supporto dello schema JSON fornito da
System.Text.Json
. - È compatibile con AoT nativo.
Installazione del pacchetto
Installare il pacchetto Microsoft.AspNetCore.OpenApi
:
Eseguire il comando seguente dalla console di Gestione pacchetti:
Install-Package Microsoft.AspNetCore.OpenApi
Configurare la generazione di documenti OpenAPI
Il codice seguente:
- Aggiunge servizi OpenAPI usando il metodo di estensione AddOpenApi nella raccolta di servizi del generatore di app.
- Esegue il mapping di un endpoint per visualizzare il documento OpenAPI in formato JSON con il metodo di estensione MapOpenApi nell'applicazione.
var builder = WebApplication.CreateBuilder();
builder.Services.AddOpenApi();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.MapOpenApi();
}
app.MapGet("/", () => "Hello world!");
app.Run();
Avviare l'app e passare a https://localhost:<port>/openapi/v1.json
per visualizzare il documento OpenAPI generato.
Opzioni per personalizzare la generazione di documenti OpenAPI
Le sezioni seguenti illustrano come personalizzare la generazione di documenti OpenAPI.
Personalizzare il nome del documento OpenAPI
Ogni documento OpenAPI in un'app ha un nome univoco. Il nome del documento predefinito registrato è v1
.
builder.Services.AddOpenApi(); // Document name is v1
Il nome del documento può essere modificato passando il nome come parametro alla AddOpenApi chiamata.
builder.Services.AddOpenApi("internal"); // Document name is internal
Il nome del documento viene visualizzato in diverse posizioni nell'implementazione OpenAPI.
Quando si recupera il documento OpenAPI generato, il nome del documento viene fornito come argomento del documentName
parametro nella richiesta. Le seguenti richieste trattano i documenti v1
e internal
.
GET http://localhost:5000/openapi/v1.json
GET http://localhost:5000/openapi/internal.json
Personalizzare la versione OpenAPI di un documento generato
Per impostazione predefinita, la generazione di documenti OpenAPI crea un documento conforme alla versione 3.0 della specifica OpenAPI. Il codice seguente illustra come modificare la versione predefinita del documento OpenAPI:
builder.Services.AddOpenApi(options =>
{
options.OpenApiVersion = OpenApiSpecVersion.OpenApi2_0;
});
Personalizzare la route dell'endpoint OpenAPI
Per impostazione predefinita, l'endpoint OpenAPI registrato tramite una chiamata a MapOpenApi espone il documento all'endpoint /openapi/{documentName}.json
. Il codice seguente illustra come personalizzare la route in cui è registrato il documento OpenAPI:
app.MapOpenApi("/openapi/{documentName}/openapi.json");
È possibile, ma non consigliato, rimuovere il documentName
parametro di route dalla route dell'endpoint. Quando il parametro di route documentName
viene rimosso dalla route dell'endpoint, il framework tenta di determinare il nome del documento dal parametro di query. La mancata fornitura dell'elemento documentName
nella route o nella query può causare effetti imprevisti.
Personalizzare l'endpoint OpenAPI
Poiché il documento OpenAPI viene fornito tramite un endpoint del gestore di route, qualsiasi personalizzazione disponibile per gli endpoint minimi standard è disponibile per l'endpoint OpenAPI.
Limitare l'accesso ai documenti OpenAPI agli utenti autorizzati
L'endpoint OpenAPI non abilita i controlli di autorizzazione per impostazione predefinita. Tuttavia, i controlli di autorizzazione possono essere applicati al documento OpenAPI. Nel codice seguente, l'accesso al documento OpenAPI è limitato a quelli con il tester
ruolo :
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.OpenApi;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.OpenApi.Models;
var builder = WebApplication.CreateBuilder();
builder.Services.AddAuthentication().AddJwtBearer();
builder.Services.AddAuthorization(o =>
{
o.AddPolicy("ApiTesterPolicy", b => b.RequireRole("tester"));
});
builder.Services.AddOpenApi();
var app = builder.Build();
app.MapOpenApi()
.RequireAuthorization("ApiTesterPolicy");
app.MapGet("/", () => "Hello world!");
app.Run();
Documento OpenAPI generato nella cache
Il documento OpenAPI viene rigenerato ogni volta che viene inviata una richiesta all'endpoint OpenAPI. La rigenerazione consente ai trasformatori di incorporare lo stato dinamico dell'applicazione nel loro funzionamento. Ad esempio, rigenerando una richiesta con i dettagli del contesto HTTP. Se applicabile, il documento OpenAPI può essere memorizzato nella cache per evitare di eseguire la pipeline di generazione di documenti in ogni richiesta HTTP.
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.OpenApi;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.OpenApi.Models;
var builder = WebApplication.CreateBuilder();
builder.Services.AddOutputCache(options =>
{
options.AddBasePolicy(policy => policy.Expire(TimeSpan.FromMinutes(10)));
});
builder.Services.AddOpenApi();
var app = builder.Build();
app.UseOutputCache();
if (app.Environment.IsDevelopment())
{
app.MapOpenApi()
.CacheOutput();
}
app.MapGet("/", () => "Hello world!");
app.Run();
Generare più documenti OpenAPI
In alcuni scenari, è utile generare più documenti OpenAPI con contenuto diverso da un'unica app per le API core ASP.NET. Questi scenari sono:
- Generazione di documentazione OpenAPI per gruppi di destinatari diversi, ad esempio API pubbliche e interne.
- Generazione della documentazione openAPI per versioni diverse di un'API.
- Generazione della documentazione openAPI per diverse parti di un'app, ad esempio un front-end e un'API back-end.
Per generare più documenti OpenAPI, chiamare il metodo di estensione AddOpenApi una volta per ogni documento, specificando un nome di documento diverso nel primo parametro ogni volta.
builder.Services.AddOpenApi("v1");
builder.Services.AddOpenApi("v2");
Ogni chiamata di AddOpenApi può specificare il proprio set di opzioni, in modo da poter scegliere di usare le stesse personalizzazioni o diverse per ogni documento OpenAPI.
Il framework utilizza il metodo delegato ShouldInclude di OpenApiOptions per determinare quali endpoint includere negli documenti.
Per ogni documento, viene chiamato il metodo delegato ShouldInclude per ogni endpoint nell'app, passando l'oggetto ApiDescription per l'endpoint. Il metodo restituisce un valore booleano che indica se l'endpoint deve essere incluso nel documento. Oggetto ApiDescription:
- contiene informazioni sull'endpoint, ad esempio il metodo HTTP, la route e i tipi di risposta
- Metadati collegati all'endpoint tramite attributi o metodi di estensione.
L'implementazione predefinita di questo delegato usa il campo GroupName di ApiDescription. Il delegato viene impostato su un endpoint usando il metodo di estensione WithGroupName o l'attributo EndpointGroupNameAttribute.
WithGroupName
o l'attributo EndpointGroupName
determina quali endpoint includere nel documento. Tutti gli endpoint a cui non è stato assegnato un nome di gruppo sono inclusi in tutti i documenti OpenAPI.
// Include endpoints without a group name or with a group name that matches the document name
ShouldInclude = (description) => description.GroupName == null || description.GroupName == DocumentName;
È possibile personalizzare il metodo delegato ShouldInclude per includere o escludere gli endpoint in base a qualsiasi criterio scelto.
Generare documenti OpenAPI in fase di compilazione
Nelle app Web tipiche, i documenti OpenAPI vengono generati in fase di esecuzione e gestiti tramite una richiesta HTTP al server app.
In alcuni scenari, è utile generare il documento OpenAPI durante il passaggio di compilazione dell'app. Questi scenari sono:
- Generazione della documentazione OpenAPI che viene inserita nel controllo del codice sorgente.
- Generazione della documentazione openAPI usata per i test di integrazione basati su specifiche.
- Generazione della documentazione OpenAPI fornita in modo statico dal server Web.
Per aggiungere il supporto per la generazione di documenti OpenAPI in fase di compilazione, installare il Microsoft.Extensions.ApiDescription.Server
pacchetto:
Eseguire il comando seguente dalla console di Gestione pacchetti:
Install-Package Microsoft.Extensions.ApiDescription.Server
Al momento dell'installazione, questo pacchetto:
- Genera automaticamente i documenti open API associati all'app durante la compilazione.
- Popola i documenti open API nella directory di output dell'app.
Se sono registrati più documenti, il nome del documento e è e nonv1
, e viene post-fissato con il nome del documento. Ad esempio {ProjectName}_{DocumentName}.json
.
dotnet build
type obj\{ProjectName}.json
Personalizzazione della generazione di documenti in fase di compilazione
Modifica della directory di output del file Open API generato
Per impostazione predefinita, il documento OpenAPI generato verrà generato nella directory di output dell'app. Per modificare il percorso del file generato, impostare il percorso di destinazione nella OpenApiDocumentsDirectory
proprietà .
<PropertyGroup>
<OpenApiDocumentsDirectory>.</OpenApiDocumentsDirectory>
</PropertyGroup>
Il valore di OpenApiDocumentsDirectory
viene risolto in relazione al file di progetto. L'uso del .
valore precedente genererà il documento OpenAPI nella stessa directory del file di progetto.
Modifica del nome del file di output
Per impostazione predefinita, il documento OpenAPI generato avrà lo stesso nome del file di progetto dell'app. Per modificare il nome del file generato, impostare l'argomento --file-name
della proprietà OpenApiGenerateDocumentsOptions
.
<PropertyGroup>
<OpenApiGenerateDocumentsOptions>--file-name my-open-api</OpenApiGenerateDocumentsOptions>
</PropertyGroup>
Selezione del documento OpenAPI da generare
Alcune app possono essere configurate per generare più documenti OpenAPI. È possibile generare più documenti OpenAPI per versioni diverse di un'API o distinguere tra API pubbliche e interne. Per impostazione predefinita, il generatore di documenti in fase di compilazione genera file per tutti i documenti configurati in un'app. Per generare solo per un singolo nome di documento, impostare l'argomento --document-name
nella proprietà OpenApiGenerateDocumentsOptions
.
<PropertyGroup>
<OpenApiGenerateDocumentsOptions>--document-name v2</OpenApiGenerateDocumentsOptions>
</PropertyGroup>
Personalizzazione del comportamento di runtime durante la generazione di documenti in fase di compilazione
Funzioni di generazione di documenti OpenAPI in fase di compilazione avviando il punto di ingresso dell'applicazione utilizzando un’implementazione simulata del server. È necessario un server fittizio per produrre documenti OpenAPI accurati perché tutte le informazioni nel documento OpenAPI non possono essere analizzate in modo statico. Poiché viene richiamato il punto di ingresso delle app, viene richiamata qualsiasi logica nell'avvio delle app. Questo include il codice che inserisce i servizi nel contenitore di DI o legge dalla configurazione. In alcuni scenari, è necessario limitare i percorsi di codice che verranno eseguiti quando il punto di ingresso delle app viene richiamato dalla generazione di documenti in fase di compilazione. Questi scenari sono:
- Non leggendo da determinate stringhe di configurazione.
- Non registra i servizi correlati al database.
Per impedire che questi percorsi di codice vengano richiamati dalla pipeline di generazione in fase di compilazione, possono essere condizionati dietro un controllo sull'assembly di ingresso.
using System.Reflection;
var builder = WebApplication.CreateBuilder(args);
if (Assembly.GetEntryAssembly()?.GetName().Name != "GetDocument.Insider")
{
builder.AddServiceDefaults();
}
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error", createScopeForErrors: true);
app.UseHsts();
}
var myKeyValue = app.Configuration["MyKey"];
app.MapGet("/", () => {
return Results.Ok($"The value of MyKey is: {myKeyValue}");
})
.WithName("TestKey");
app.Run();
AddServiceDefaults aggiunge servizi di .NET Aspire comuni, ad esempio l'individuazione dei servizi, la resilienza, i controlli di integrità e OpenTelemetry.
Ottimizzazione e AOT nativo
OpenAPI in ASP.NET Core supporta il trimming e l'AOT nativo. La procedura seguente consente di creare e pubblicare un'app OpenAPI con ottimizzazione e AOT nativo.
Creare un nuovo progetto di ASP.NET Core Web API (Native AOT).
dotnet new webapiaot
Aggiungere il pacchetto Microsoft.AspNetCore.OpenAPI.
dotnet add package Microsoft.AspNetCore.OpenApi
Aggiornare Program.cs
per abilitare la generazione di documenti OpenAPI.
+ builder.Services.AddOpenApi();
var app = builder.Build();
+ app.MapOpenApi();
Pubblicare l'app.
dotnet publish
Le API minime offrono il supporto predefinito per la generazione di informazioni sugli endpoint in un'app tramite il Microsoft.AspNetCore.OpenApi
pacchetto. L'esposizione della definizione OpenAPI generata tramite un'interfaccia utente visiva richiede un pacchetto di terze parti. Per informazioni sul supporto per OpenAPI nelle API basate su controller, vedere la versione .NET 9 di questo articolo.
Il codice seguente viene generato dal modello api Web minimo di ASP.NET core e usa OpenAPI:
using Microsoft.AspNetCore.OpenApi;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
var summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
app.MapGet("/weatherforecast", () =>
{
var forecast = Enumerable.Range(1, 5).Select(index =>
new WeatherForecast
(
DateTime.Now.AddDays(index),
Random.Shared.Next(-20, 55),
summaries[Random.Shared.Next(summaries.Length)]
))
.ToArray();
return forecast;
})
.WithName("GetWeatherForecast")
.WithOpenApi();
app.Run();
internal record WeatherForecast(DateTime Date, int TemperatureC, string? Summary)
{
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
}
Nel codice evidenziato precedente:
-
Microsoft.AspNetCore.OpenApi
viene spiegato nella sezione successiva. -
AddEndpointsApiExplorer : configura l'app per l'uso di Esplora API per individuare e descrivere gli endpoint con annotazioni predefinite.
WithOpenApi
sostituisce le annotazioni predefinite corrispondenti generate da API Explorer con quelle prodotte dal pacchettoMicrosoft.AspNetCore.OpenApi
. -
UseSwagger
aggiunge il Swagger middleware. - 'UseSwaggerUI' abilita una versione incorporata dello strumento dell'interfaccia utente di Swagger.
- WithName: L'IEndpointNameMetadata nell'endpoint viene usato per la generazione di collegamenti ed è trattato come l'ID operazione nella specifica OpenAPI dell'endpoint specificato.
-
WithOpenApi
viene spiegato più avanti in questo articolo.
pacchetto NuGet Microsoft.AspNetCore.OpenApi
ASP.NET Core fornisce il Microsoft.AspNetCore.OpenApi
pacchetto per interagire con le specifiche OpenAPI per gli endpoint. Il pacchetto funge da collegamento tra i modelli OpenAPI definiti nel Microsoft.AspNetCore.OpenApi
pacchetto e gli endpoint definiti nelle API minime. Il pacchetto fornisce un'API che esamina i parametri, le risposte e i metadati di un endpoint per costruire un tipo di annotazione OpenAPI usato per descrivere un endpoint.
Microsoft.AspNetCore.OpenApi
viene aggiunto come PackageReference a un file di progetto:
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="7.0.*-*" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
</ItemGroup>
</Project>
Quando si usa Swashbuckle.AspNetCore
con Microsoft.AspNetCore.OpenApi
, è necessario usare la Swashbuckle.AspNetCore
versione 6.4.0 o successiva.
Microsoft.OpenApi
1.4.3 o versione successiva devono essere usati per sfruttare i costruttori di copia nelle WithOpenApi
chiamate.
Aggiungere annotazioni OpenAPI agli endpoint tramite WithOpenApi
La chiamata WithOpenApi
all'endpoint aggiunge ai metadati dell'endpoint stesso. Questi metadati possono essere:
- Utilizzato in pacchetti di terze parti come Swashbuckle.AspNetCore.
- Visualizzato nell'interfaccia utente di Swagger o in YAML o JSON generato per definire l'API.
app.MapPost("/todoitems/{id}", async (int id, Todo todo, TodoDb db) =>
{
todo.Id = id;
db.Todos.Add(todo);
await db.SaveChangesAsync();
return Results.Created($"/todoitems/{todo.Id}", todo);
})
.WithOpenApi();
Modificare l'annotazione OpenAPI in WithOpenApi
Il WithOpenApi
metodo accetta una funzione che può essere usata per modificare l'annotazione OpenAPI. Nel codice seguente, ad esempio, viene aggiunta una descrizione al primo parametro dell'endpoint:
app.MapPost("/todo2/{id}", async (int id, Todo todo, TodoDb db) =>
{
todo.Id = id;
db.Todos.Add(todo);
await db.SaveChangesAsync();
return Results.Created($"/todoitems/{todo.Id}", todo);
})
.WithOpenApi(generatedOperation =>
{
var parameter = generatedOperation.Parameters[0];
parameter.Description = "The ID associated with the created Todo";
return generatedOperation;
});
Aggiungere ID operazione a OpenAPI
Gli ID operazione vengono usati per identificare in modo univoco un determinato endpoint in OpenAPI. Il WithName
metodo di estensione può essere usato per impostare l'ID operazione utilizzato per un metodo.
app.MapGet("/todoitems2", async (TodoDb db) =>
await db.Todos.ToListAsync())
.WithName("GetToDoItems");
In alternativa, la OperationId
proprietà può essere impostata direttamente nell'annotazione OpenAPI.
app.MapGet("/todos", async (TodoDb db) => await db.Todos.ToListAsync())
.WithOpenApi(operation => new(operation)
{
OperationId = "GetTodos"
});
Aggiungere tag alla descrizione OpenAPI
OpenAPI supporta l'uso di oggetti tag per classificare le operazioni. Questi tag vengono in genere usati per raggruppare le operazioni nell'interfaccia utente di Swagger. Questi tag possono essere aggiunti a un'operazione richiamando il metodo di estensione WithTags nell'endpoint con i tag desiderati.
app.MapGet("/todoitems", async (TodoDb db) =>
await db.Todos.ToListAsync())
.WithTags("TodoGroup");
In alternativa, l'elenco di OpenApiTags
può essere impostato nell'annotazione OpenAPI tramite il WithOpenApi
metodo di estensione.
app.MapGet("/todos", async (TodoDb db) => await db.Todos.ToListAsync())
.WithOpenApi(operation => new(operation)
{
Tags = new List<OpenApiTag> { new() { Name = "Todos" } }
});
Aggiungi il riepilogo o la descrizione dell'endpoint
Il riepilogo e la descrizione dell'endpoint possono essere aggiunti richiamando il WithOpenApi
metodo di estensione. Nel codice seguente i riepiloghi vengono impostati direttamente nell'annotazione OpenAPI.
app.MapGet("/todoitems2", async (TodoDb db) => await db.Todos.ToListAsync())
.WithOpenApi(operation => new(operation)
{
Summary = "This is a summary",
Description = "This is a description"
});
Escludere la descrizione OpenAPI
Nell'esempio seguente l'endpoint /skipme
viene escluso dalla generazione di una descrizione OpenAPI:
using Microsoft.AspNetCore.OpenApi;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.MapGet("/swag", () => "Hello Swagger!")
.WithOpenApi();
app.MapGet("/skipme", () => "Skipping Swagger.")
.ExcludeFromDescription();
app.Run();
Contrassegnare un'API come obsoleta
Per contrassegnare un endpoint come obsoleto, impostare la proprietà Deprecated
nell'annotazione OpenAPI.
app.MapGet("/todos", async (TodoDb db) => await db.Todos.ToListAsync())
.WithOpenApi(operation => new(operation)
{
Deprecated = true
});
Descrivere i tipi di risposta
OpenAPI supporta la descrizione delle risposte restituite da un'API. Le API minime supportano tre strategie per impostare il tipo di risposta di un endpoint:
- Tramite il metodo di estensione
Produces
sull'endpoint - Tramite l'attributo
ProducesResponseType
nell'handler di route - Restituendo
TypedResults
dal gestore di route
Il Produces
metodo di estensione può essere usato per aggiungere Produces
metadati a un endpoint. Quando non vengono forniti parametri, il metodo di estensione popola i metadati per il tipo di destinazione con un 200
codice di stato e un application/json
tipo di contenuto.
app
.MapGet("/todos", async (TodoDb db) => await db.Todos.ToListAsync())
.Produces<IList<Todo>>();
L'uso TypedResults
nell'implementazione del gestore di route di un endpoint include automaticamente i metadati del tipo di risposta per l'endpoint. Ad esempio, il codice seguente annota automaticamente l'endpoint con una risposta con un tipo di contenuto application/json
sotto il codice di stato 200
.
app.MapGet("/todos", async (TodoDb db) =>
{
var todos = await db.Todos.ToListAsync());
return TypedResults.Ok(todos);
});
Impostare le risposte per ProblemDetails
Quando si imposta il tipo di risposta per gli endpoint che possono restituire una risposta ProblemDetails, è possibile utilizzare il metodo di estensione ProducesProblem, ProducesValidationProblem o TypedResults.Problem
per aggiungere l'annotazione appropriata ai metadati dell'endpoint. Si noti che i metodi di estensione ProducesProblem
e ProducesValidationProblem
non possono essere utilizzati con i gruppi di route in .NET 8 e nelle versioni precedenti.
Quando non sono presenti annotazioni esplicite fornite da una delle strategie precedenti, il framework tenta di determinare un tipo di risposta predefinito esaminando la firma della risposta. Questa risposta predefinita viene popolata sotto il 200
codice di stato nella definizione OpenAPI.
Più tipi di risposta
Se un endpoint può restituire tipi di risposta diversi in scenari diversi, è possibile fornire metadati nei modi seguenti:
Chiamare il
Produces
metodo di estensione più volte, come illustrato nell'esempio seguente:app.MapGet("/api/todoitems/{id}", async (int id, TodoDb db) => await db.Todos.FindAsync(id) is Todo todo ? Results.Ok(todo) : Results.NotFound()) .Produces<Todo>(StatusCodes.Status200OK) .Produces(StatusCodes.Status404NotFound);
Usare
Results<TResult1,TResult2,TResultN>
nella firma eTypedResults
nel corpo del gestore, come illustrato nell'esempio seguente:app.MapGet("/book/{id}", Results<Ok<Book>, NotFound> (int id, List<Book> bookList) => { return bookList.FirstOrDefault((i) => i.Id == id) is Book book ? TypedResults.Ok(book) : TypedResults.NotFound(); });
I
Results<TResult1,TResult2,TResultN>
tipi unione dichiarano che un gestore di route restituisce più tipi concreti che implementanoIResult
, e qualsiasi di questi tipi che implementaIEndpointMetadataProvider
contribuirà ai metadati dell'endpoint.I tipi di unione implementano operatori cast impliciti. Questi operatori consentono al compilatore di convertire automaticamente i tipi specificati negli argomenti generici in un'istanza del tipo di unione. Questa funzionalità offre il vantaggio aggiunto di fornire un controllo in fase di compilazione che un gestore di route restituisce solo i risultati che dichiara. Tentare di restituire un tipo che non è dichiarato come uno degli argomenti generici a
Results<TResult1,TResult2,TResultN>
comporta un errore di compilazione.
Descrivere il corpo e i parametri della richiesta
Oltre a descrivere i tipi restituiti da un endpoint, OpenAPI supporta anche l'annotazione degli input utilizzati da un'API. Questi input rientrano in due categorie:
- Parametri visualizzati nel percorso, nella stringa di query, nelle intestazioni o nei cookie
- Dati trasmessi come parte del corpo della richiesta
Il framework deduce automaticamente i tipi per i parametri della richiesta nel percorso, nella query e nella stringa di intestazione in base alla firma del gestore di route.
Per definire il tipo di input trasmesso come corpo della richiesta, configurare le proprietà usando il Accepts
metodo di estensione per definire il tipo di oggetto e il tipo di contenuto previsti dal gestore della richiesta. Nell'esempio seguente l'endpoint accetta un Todo
oggetto nel corpo della richiesta con un tipo di contenuto previsto di application/xml
.
app.MapPost("/todos/{id}", (int id, Todo todo) => ...)
.Accepts<Todo>("application/xml");
Oltre al Accepts
metodo di estensione, un tipo di parametro può descrivere la propria annotazione implementando l'interfaccia IEndpointParameterMetadataProvider
. Ad esempio, il tipo seguente Todo
aggiunge un'annotazione che richiede un corpo della richiesta con un application/xml
tipo di contenuto.
public class Todo : IEndpointParameterMetadataProvider
{
public static void PopulateMetadata(ParameterInfo parameter, EndpointBuilder builder)
{
builder.Metadata.Add(new ConsumesAttribute(typeof(Todo), isOptional: false, "application/xml"));
}
}
Quando non viene fornita alcuna annotazione esplicita, il framework tenta di determinare il tipo di richiesta predefinito se è presente un parametro del corpo della richiesta nel gestore dell'endpoint. L'inferenza usa le euristiche seguenti per produrre l'annotazione:
- I parametri del corpo della richiesta letti da un modulo tramite l'attributo
[FromForm]
vengono descritti con ilmultipart/form-data
tipo di contenuto. - Tutti gli altri parametri del corpo della richiesta sono descritti con il
application/json
tipo di contenuto. - Il corpo della richiesta viene considerato facoltativo se può essere nullo o se la proprietà
AllowEmpty
è impostata sull'attributoFromBody
.
Supporto del controllo delle versioni delle API
Le API minime supportano il controllo delle versioni delle API tramite il pacchetto Asp.Versioning.Http. Esempi di configurazione del controllo delle versioni con API minime sono disponibili nel repository di controllo delle versioni dell'API.
Codice sorgente OpenAPI di ASP.NET Core su GitHub
Risorse aggiuntive
Un'app API minima può descrivere la specifica OpenAPI per i gestori di route usando Swashbuckle.
Per informazioni sul supporto per OpenAPI nelle API basate su controller, vedere la versione .NET 9 di questo articolo.
Il codice seguente è un'app ASP.NET Core tipica con supporto OpenAPI:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new() { Title = builder.Environment.ApplicationName,
Version = "v1" });
});
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseSwagger(); // UseSwaggerUI Protected by if (env.IsDevelopment())
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json",
$"{builder.Environment.ApplicationName} v1"));
}
app.MapGet("/swag", () => "Hello Swagger!");
app.Run();
Escludere la descrizione OpenAPI
Nell'esempio seguente l'endpoint /skipme
viene escluso dalla generazione di una descrizione OpenAPI:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI(); // UseSwaggerUI Protected by if (env.IsDevelopment())
}
app.MapGet("/swag", () => "Hello Swagger!");
app.MapGet("/skipme", () => "Skipping Swagger.")
.ExcludeFromDescription();
app.Run();
Descrivere i tipi di risposta
Nell'esempio seguente vengono usati i tipi di risultati predefiniti per personalizzare la risposta:
app.MapGet("/api/todoitems/{id}", async (int id, TodoDb db) =>
await db.Todos.FindAsync(id)
is Todo todo
? Results.Ok(todo)
: Results.NotFound())
.Produces<Todo>(StatusCodes.Status200OK)
.Produces(StatusCodes.Status404NotFound);
Aggiungere gli ID operazioni a OpenAPI
app.MapGet("/todoitems2", async (TodoDb db) =>
await db.Todos.ToListAsync())
.WithName("GetToDoItems");
Aggiungere tag alla descrizione OpenAPI
Il codice seguente usa un tag di raggruppamento OpenAPI:
app.MapGet("/todoitems", async (TodoDb db) =>
await db.Todos.ToListAsync())
.WithTags("TodoGroup");