Share via


Prise en charge d’OpenAPI dans les applications API minimales

La spécification OpenAPI est une norme indépendante du langage de programmation pour documenter les API HTTP. Cette norme est prise en charge dans les API minimales par le biais d’une combinaison d’API intégrées et de bibliothèques open source. L’intégration d’OpenAPI dans une application comporte trois aspects clés :

  • Génération d’informations sur les points de terminaison dans l’application.
  • Collecte des informations dans un format qui correspond au schéma OpenAPI.
  • Exposition du schéma OpenAPI généré via une interface utilisateur visuelle ou un fichier sérialisé.

Les API minimales fournissent une prise en charge intégrée de la génération d’informations sur les points de terminaison dans une application via le package Microsoft.AspNetCore.OpenApi.

Le code suivant est généré par le modèle d’API web minimal ASP.NET Core et utilise OpenAPI :

using Microsoft.AspNetCore.OpenApi;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddOpenApi();

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.MapOpenApi();
}

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

app.Run();

internal record WeatherForecast(DateTime Date, int TemperatureC, string? Summary)
{
    public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
}

Dans le code en surbrillance précédent :

  • AddOpenApi inscrit les services nécessaires à la génération de documents OpenAPI dans le conteneur DI de l’application.
  • MapOpenApi ajoute un point de terminaison dans l’application pour afficher le document OpenAPI sérialisé en JSON.

package NuGet Microsoft.AspNetCore.OpenApi

Le package Microsoft.AspNetCore.OpenApi propose des fonctionnalités qui englobent les fonctionnalités suivantes :

  • Prise en charge de la génération de documents OpenAPI au moment de l’exécution et de leur accès via un point de terminaison au niveau de l’application
  • Prise en charge des API de type « transformateur » qui permettent de modifier le document généré
  • Prise en charge de la génération de documents OpenAPI au moment de la génération et de leur sérialisation sur disque

Microsoft.AspNetCore.OpenApi est ajouté en tant que PackageReference à un fichier projet :

<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>net9.0</TargetFramework>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
  </PropertyGroup>

  <ItemGroup>    
    <PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.*-*" />
  </ItemGroup>

</Project>

Décrire des types de réponse

OpenAPI prend en charge la description des réponses retournées par une API. Les API minimales prennent en charge trois stratégies pour définir le type de réponse d’un point de terminaison :

  • Via la méthode d’extension Produces au niveau du point de terminaison.
  • Via l’attribut ProducesResponseType au niveau du gestionnaire de routage.
  • En retournant TypedResults à partir du gestionnaire de routage.

Il est possible d’utiliser la méthode d’extension Produces pour ajouter des métadonnées Produces à un point de terminaison. Quand aucun paramètre n’est fourni, la méthode d’extension remplit les métadonnées pour le type ciblé sous un code d’état 200 et un type de contenu application/json.

app
    .MapGet("/todos", async (TodoDb db) => await db.Todos.ToListAsync())
    .Produces<IList<Todo>>();

L’utilisation de TypedResults dans l’implémentation du gestionnaire de routage d’un point de terminaison inclut automatiquement les métadonnées du type de réponse pour le point de terminaison. Par exemple, le code suivant annote automatiquement le point de terminaison avec une réponse sous le code d’état 200 avec un type de contenu application/json.

app.MapGet("/todos", async (TodoDb db) =>
{
    var todos = await db.Todos.ToListAsync());
    return TypedResults.Ok(todos);
});

Définir des réponses pour ProblemDetails

Lors de la définition du type de réponse pour les points de terminaison susceptibles de renvoyer une réponse ProblemDetails, la méthode d’extension ProducesProblem ou TypedResults.Problem peut être utilisée pour ajouter l’annotation appropriée aux métadonnées du point de terminaison.

Lorsqu’aucune annotation explicite n’est fournie par l’une de ces stratégies, l’infrastructure tente de déterminer un type de réponse par défaut en examinant la signature de la réponse. Cette réponse par défaut est remplie sous le code d’état 200 dans la définition OpenAPI.

Types de réponse multiples

Si un point de terminaison peut retourner différents types de réponse dans différents scénarios, vous pouvez fournir des métadonnées des manières suivantes :

  • Appeler la méthode d’extension Produces plusieurs fois, comme illustré dans l’exemple suivant :

    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);
    
  • Utiliser Results<TResult1,TResult2,TResultN> dans la signature et TypedResults dans le corps du gestionnaire, comme illustré dans l’exemple suivant :

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

    Les Results<TResult1,TResult2,TResultN>types d’union déclarent qu’un gestionnaire de routage retourne plusieurs types concrets implémentant IResult, et tous les types qui implémentent IEndpointMetadataProvider contribueront aux métadonnées du point de terminaison.

    Les types d’union implémentent des opérateurs de cast implicites. Ces opérateurs permettent au compilateur de convertir automatiquement les types spécifiés dans les arguments génériques en instance du type union. Cette fonctionnalité présente l’avantage supplémentaire de vérifier au moment de la compilation qu’un gestionnaire de routage retourne uniquement les résultats qu’il déclare faire. La tentative de retourner un type qui n’est pas déclaré comme l’un des arguments génériques vers Results<TResult1,TResult2,TResultN> entraîne une erreur de compilation.

Décrire le corps et les paramètres de la requête

En plus de décrire les types retournés par un point de terminaison, OpenAPI prend également en charge l’annotation des entrées consommées par une API. Ces entrées se répartissent en deux catégories :

  • Paramètres qui apparaissent dans le chemin d’accès, la chaîne de requête, les en-têtes ou les cookies.
  • Données transmises dans le corps de la demande.

L’infrastructure déduit automatiquement les types des paramètres de requête dans le chemin d’accès, la requête et la chaîne d’en-tête en fonction de la signature du gestionnaire de routage.

Pour définir le type d’entrées transmises en tant que corps de la demande, configurez les propriétés à l’aide de la méthode d’extension Accepts pour définir le type d’objet et le type de contenu attendus par le gestionnaire de requêtes. Dans l’exemple suivant, le point de terminaison accepte un objet Todo dans le corps de la requête avec un type de contenu attendu de application/xml.

app.MapPost("/todos/{id}", (int id, Todo todo) => ...)
  .Accepts<Todo>("application/xml");

En plus de la méthode d’extension Accepts, un type de paramètre peut décrire sa propre annotation en implémentant l’interface IEndpointParameterMetadataProvider. Par exemple, le type Todo suivant ajoute une annotation qui nécessite un corps de requête avec un type de contenu application/xml.

public class Todo : IEndpointParameterMetadataProvider
{
    public static void PopulateMetadata(ParameterInfo parameter, EndpointBuilder builder)
    {
        builder.Metadata.Add(new ConsumesAttribute(typeof(Todo), isOptional: false, "application/xml"));
    }
}

Lorsqu’aucune annotation explicite n’est fournie, l’infrastructure tente de déterminer le type de requête par défaut s’il existe un paramètre de corps de la demande dans le gestionnaire de point de terminaison. L’inférence utilise l’heuristique suivante pour produire l’annotation :

  • Les paramètres du corps de la requête qui sont lus à partir d’un formulaire via l’attribut [FromForm] sont décrits avec le type de contenu multipart/form-data.
  • Tous les autres paramètres du corps de la requête sont décrits avec le type de contenu application/json.
  • Le corps de la requête est traité comme facultatif s’il peut avoir la valeur Null ou si la propriété AllowEmpty est définie sur l’attribut FromBody.

Code source OpenAPI d’ASP.NET Core sur GitHub

Ressources complémentaires

La spécification OpenAPI est une norme indépendante du langage de programmation pour documenter les API HTTP. Cette norme est prise en charge dans les API minimales par le biais d’une combinaison d’API intégrées et de bibliothèques open source. L’intégration d’OpenAPI dans une application comporte trois aspects clés :

  • Génération d’informations sur les points de terminaison dans l’application.
  • Collecte des informations dans un format qui correspond au schéma OpenAPI.
  • Exposition du schéma OpenAPI généré via une interface utilisateur visuelle ou un fichier sérialisé.

Les API minimales fournissent une prise en charge intégrée de la génération d’informations sur les points de terminaison dans une application via le package Microsoft.AspNetCore.OpenApi. L’exposition de la définition OpenAPI générée via une interface utilisateur visuelle nécessite un package tiers.

Le code suivant est généré par le modèle d’API web minimal ASP.NET Core et utilise 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);
}

Dans le code en surbrillance précédent :

  • Microsoft.AspNetCore.OpenApi est expliqué dans la section suivante.
  • AddEndpointsApiExplorer : configure l’application afin d’utiliser l’API Explorer pour découvrir et décrire des points de terminaison avec des annotations par défaut. WithOpenApi remplace la correspondance, les annotations par défaut générées par l’API Explorer avec celles produites à partir du package Microsoft.AspNetCore.OpenApi.
  • UseSwagger ajoute l’intergiciel Swagger.
  • `UseSwaggerUI` active une version incorporée de l’outil de l’interface utilisateur Swagger.
  • WithName : le IEndpointNameMetadata sur le point de terminaison est utilisé pour la génération de liens et est traité comme l’ID d’opération dans la spécification OpenAPI du point de terminaison donné.
  • WithOpenApi est expliqué plus loin dans cet article.

package NuGet Microsoft.AspNetCore.OpenApi

ASP.NET Core fournit le package Microsoft.AspNetCore.OpenApi pour interagir avec les spécifications OpenAPI pour les points de terminaison. Le package agit comme un lien entre les modèles OpenAPI définis dans le package Microsoft.AspNetCore.OpenApi et les points de terminaison définis dans les API minimales. Le package fournit une API qui examine les paramètres, les réponses et les métadonnées d’un point de terminaison pour construire un type d’annotation OpenAPI utilisé pour décrire un point de terminaison.

Microsoft.AspNetCore.OpenApi est ajouté en tant que PackageReference à un fichier projet :

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

Lors de l’utilisation de Swashbuckle.AspNetCore avec Microsoft.AspNetCore.OpenApi, Swashbuckle.AspNetCore version 6.4.0 ou ultérieure doit être utilisée. Microsoft.OpenApi version 1.4.3 ou ultérieure doit être utilisée pour tirer parti des constructeurs de copie dans les appels WithOpenApi.

Ajouter des annotations OpenAPI aux points de terminaison via WithOpenApi

Appeler WithOpenApi sur le point de terminaison permet l’ajout aux métadonnées du point de terminaison. Ces métadonnées peuvent être :

  • Consommées dans des packages tiers comme Swashbuckle.AspNetCore.
  • Affichées dans l’interface utilisateur Swagger ou en YAML ou JSON généré pour définir 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();

Modifier l’annotation OpenAPI dans WithOpenApi

La méthode WithOpenApi accepte une fonction qui peut être utilisée pour modifier l’annotation OpenAPI. Par exemple, dans le code suivant, une description est ajoutée au premier paramètre du point de terminaison :

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

Ajouter des ID d’opération à OpenAPI

Les ID d’opération sont utilisés pour identifier de manière unique un point de terminaison donné dans OpenAPI. Il est possible d’utiliser la méthode d’extension WithName pour définir l’ID d’opération utilisé pour une méthode.

app.MapGet("/todoitems2", async (TodoDb db) =>
    await db.Todos.ToListAsync())
    .WithName("GetToDoItems");

Vous pouvez également définir la propriété OperationId directement sur l’annotation OpenAPI.

app.MapGet("/todos", async (TodoDb db) => await db.Todos.ToListAsync())
    .WithOpenApi(operation => new(operation)
    {
        OperationId = "GetTodos"
    });

Ajouter des balises à la description OpenAPI

OpenAPI prend en charge l’utilisation d’objets de balise pour catégoriser les opérations. Ces balises sont généralement utilisées pour regrouper des opérations dans l’interface utilisateur de Swagger. Ces balises peuvent être ajoutées à une opération en appelant la méthode d’extension WithTags sur le point de terminaison avec les balises souhaitées.

app.MapGet("/todoitems", async (TodoDb db) =>
    await db.Todos.ToListAsync())
    .WithTags("TodoGroup");

Vous pouvez également définir la liste de OpenApiTags sur l’annotation OpenAPI via la méthode d’extension WithOpenApi .

app.MapGet("/todos", async (TodoDb db) => await db.Todos.ToListAsync())
    .WithOpenApi(operation => new(operation)
    {
        Tags = new List<OpenApiTag> { new() { Name = "Todos" } }
    });

Ajouter un résumé ou une description du point de terminaison

Le résumé et la description du point de terminaison peuvent être ajoutés en appelant la méthode d’extension WithOpenApi. Dans le code suivant, les résumés sont définis directement sur l’annotation 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"
    });

Exclure la description OpenAPI

Dans l’exemple suivant, le point de terminaison /skipme est exclu et ne peut pas générer une description 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();

Marquer une API comme obsolète

Pour marquer un point de terminaison comme obsolète, définissez la propriété Deprecated sur l’annotation OpenAPI.

app.MapGet("/todos", async (TodoDb db) => await db.Todos.ToListAsync())
    .WithOpenApi(operation => new(operation)
    {
        Deprecated = true
    });

Décrire des types de réponse

OpenAPI prend en charge la description des réponses retournées par une API. Les API minimales prennent en charge trois stratégies pour définir le type de réponse d’un point de terminaison :

  • Via la méthode d’extension Produces sur le point de terminaison
  • Via l’attribut ProducesResponseType sur le gestionnaire de routage
  • En retournant TypedResults à partir du gestionnaire de routage

Il est possible d’utiliser la méthode d’extension Produces pour ajouter des métadonnées Produces à un point de terminaison. Quand aucun paramètre n’est fourni, la méthode d’extension remplit les métadonnées pour le type ciblé sous un code d’état 200 et un type de contenu application/json.

app
    .MapGet("/todos", async (TodoDb db) => await db.Todos.ToListAsync())
    .Produces<IList<Todo>>();

L’utilisation de TypedResults dans l’implémentation du gestionnaire de routage d’un point de terminaison inclut automatiquement les métadonnées du type de réponse pour le point de terminaison. Par exemple, le code suivant annote automatiquement le point de terminaison avec une réponse sous le code d’état 200 avec un type de contenu application/json.

app.MapGet("/todos", async (TodoDb db) =>
{
    var todos = await db.Todos.ToListAsync());
    return TypedResults.Ok(todos);
});

Définir des réponses pour ProblemDetails

Lors de la définition du type de réponse pour les points de terminaison susceptibles de renvoyer une réponse ProblemDetails, la méthode d’extension ProducesProblem ou TypedResults.Problem peut être utilisée pour ajouter l’annotation appropriée aux métadonnées du point de terminaison.

Lorsqu’aucune annotation explicite n’est fournie par l’une des stratégies ci-dessus, l’infrastructure tente de déterminer un type de réponse par défaut en examinant la signature de la réponse. Cette réponse par défaut est remplie sous le code d’état 200 dans la définition OpenAPI.

Types de réponse multiples

Si un point de terminaison peut retourner différents types de réponse dans différents scénarios, vous pouvez fournir des métadonnées des manières suivantes :

  • Appeler la méthode d’extension Produces plusieurs fois, comme illustré dans l’exemple suivant :

    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);
    
  • Utiliser Results<TResult1,TResult2,TResultN> dans la signature et TypedResults dans le corps du gestionnaire, comme illustré dans l’exemple suivant :

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

    Les Results<TResult1,TResult2,TResultN>types d’union déclarent qu’un gestionnaire de routage retourne plusieurs types concrets implémentant IResult, et tous les types qui implémentent IEndpointMetadataProvider contribueront aux métadonnées du point de terminaison.

    Les types d’union implémentent des opérateurs de cast implicites. Ces opérateurs permettent au compilateur de convertir automatiquement les types spécifiés dans les arguments génériques en instance du type union. Cette fonctionnalité présente l’avantage supplémentaire de vérifier au moment de la compilation qu’un gestionnaire de routage retourne uniquement les résultats qu’il déclare faire. La tentative de retourner un type qui n’est pas déclaré comme l’un des arguments génériques vers Results<TResult1,TResult2,TResultN> entraîne une erreur de compilation.

Décrire le corps et les paramètres de la requête

En plus de décrire les types retournés par un point de terminaison, OpenAPI prend également en charge l’annotation des entrées consommées par une API. Ces entrées se répartissent en deux catégories :

  • Paramètres qui apparaissent dans le chemin d’accès, la chaîne de requête, les en-têtes ou les cookie
  • Données transmises dans le corps de la requête

L’infrastructure déduit automatiquement les types des paramètres de requête dans le chemin d’accès, la requête et la chaîne d’en-tête en fonction de la signature du gestionnaire de routage.

Pour définir le type d’entrées transmises en tant que corps de la demande, configurez les propriétés à l’aide de la méthode d’extension Accepts pour définir le type d’objet et le type de contenu attendus par le gestionnaire de requêtes. Dans l’exemple suivant, le point de terminaison accepte un objet Todo dans le corps de la requête avec un type de contenu attendu de application/xml.

app.MapPost("/todos/{id}", (int id, Todo todo) => ...)
  .Accepts<Todo>("application/xml");

En plus de la méthode d’extension Accepts, un type de paramètre peut décrire sa propre annotation en implémentant l’interface IEndpointParameterMetadataProvider. Par exemple, le type Todo suivant ajoute une annotation qui nécessite un corps de requête avec un type de contenu application/xml.

public class Todo : IEndpointParameterMetadataProvider
{
    public static void PopulateMetadata(ParameterInfo parameter, EndpointBuilder builder)
    {
        builder.Metadata.Add(new ConsumesAttribute(typeof(Todo), isOptional: false, "application/xml"));
    }
}

Lorsqu’aucune annotation explicite n’est fournie, l’infrastructure tente de déterminer le type de requête par défaut s’il existe un paramètre de corps de la demande dans le gestionnaire de point de terminaison. L’inférence utilise l’heuristique suivante pour produire l’annotation :

  • Les paramètres du corps de la requête qui sont lus à partir d’un formulaire via l’attribut [FromForm] sont décrits avec le type de contenu multipart/form-data.
  • Tous les autres paramètres du corps de la requête sont décrits avec le type de contenu application/json.
  • Le corps de la requête est traité comme facultatif s’il peut avoir la valeur Null ou si la propriété AllowEmpty est définie sur l’attribut FromBody.

Contrôle de version de l’API de support

Les API minimales prennent en charge le contrôle de version des API via le package Asp.Versioning.Http. Vous trouverez des exemples de configuration du contrôle de version avec des API minimales dans le référentiel de gestion des versions d’API.

Code source OpenAPI d’ASP.NET Core sur GitHub

Ressources supplémentaires

Une application peut décrire la spécification OpenAPI pour les gestionnaires de routage à l’aide de Swashbuckle.

Le code suivant est une application ASP.NET Core classique avec prise en charge d’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();

Exclure la description OpenAPI

Dans l’exemple suivant, le point de terminaison /skipme est exclu et ne peut pas générer une description 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();

Décrire des types de réponse

L’exemple suivant utilise les types de résultats intégrés pour personnaliser la réponse :

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

Ajouter des ID d’opération à OpenAPI

app.MapGet("/todoitems2", async (TodoDb db) =>
    await db.Todos.ToListAsync())
    .WithName("GetToDoItems");

Ajouter des balises à la description OpenAPI

Le code suivant utilise une balise de regroupement OpenAPI :

app.MapGet("/todoitems", async (TodoDb db) =>
    await db.Todos.ToListAsync())
    .WithTags("TodoGroup");