Partilhar via


Gerar documentos OpenAPI

O pacote Microsoft.AspNetCore.OpenApi fornece suporte interno para geração de documentos OpenAPI no ASP.NET Core. O pacote fornece os seguintes recursos:

  • Suporte para gerar documentos OpenAPI em tempo de execução e acessá-los através de um endpoint no aplicativo.
  • Suporte para APIs "transformer" que permitem modificar o documento gerado.
  • Suporte para gerar vários documentos OpenAPI a partir de um único aplicativo.
  • Aproveita o suporte ao esquema JSON fornecido pelo System.Text.Json.
  • É compatível com AoT nativo.

Instalação do pacote

Instale o pacote Microsoft.AspNetCore.OpenApi:

Execute o seguinte comando a partir do Console do Gerenciador de Pacotes :

Install-Package Microsoft.AspNetCore.OpenApi

Configurar a geração de documentos OpenAPI

O seguinte código:

  • Adiciona serviços OpenAPI.
  • Habilita o ponto de extremidade para visualizar o documento OpenAPI em formato JSON.
var builder = WebApplication.CreateBuilder();

builder.Services.AddOpenApi();

var app = builder.Build();

app.MapOpenApi();

app.MapGet("/", () => "Hello world!");

app.Run();

Inicie o aplicativo e navegue até https://localhost:<port>/openapi/v1.json para visualizar o documento OpenAPI gerado.

Opções para personalizar a geração de documentos OpenAPI

As seções a seguir demonstram como personalizar a geração de documentos OpenAPI.

Personalizar o nome do documento OpenAPI

Cada documento OpenAPI em um aplicativo tem um nome exclusivo. O nome do documento padrão registrado é v1.

builder.Services.AddOpenApi(); // Document name is v1

O nome do documento pode ser modificado passando o nome como um parâmetro para a chamada AddOpenApi.

builder.Services.AddOpenApi("internal"); // Document name is internal

O nome do documento aparece em vários lugares na implementação OpenAPI.

Ao buscar o documento OpenAPI gerado, o nome do documento é fornecido como o argumento de parâmetro documentName na solicitação. As seguintes solicitações resolvem os documentos v1 e internal.

GET http://localhost:5000/openapi/v1.json
GET http://localhost:5000/openapi/internal.json

Personalizar a versão OpenAPI de um documento gerado

Por padrão, a geração de documentos OpenAPI cria um documento que é compatível com v3.0 da especificação OpenAPI. O código a seguir demonstra como modificar a versão padrão do documento OpenAPI:

builder.Services.AddOpenApi(options =>
{
    options.OpenApiVersion = OpenApiSpecVersion.OpenApi2_0;
});

Personalizar a rota do endpoint OpenAPI

Por padrão, o ponto de extremidade OpenAPI registrado por meio de uma chamada para MapOpenApi expõe o documento no ponto de extremidade /openapi/{documentName}.json. O código a seguir demonstra como personalizar a rota na qual o documento OpenAPI é registrado:

app.MapOpenApi("/openapi/{documentName}/openapi.json");

É possível, mas não recomendado, remover o parâmetro documentName route da rota do ponto final. Quando o parâmetro de rota documentName é removido da rota do ponto de extremidade, a estrutura tenta resolver o nome do documento a partir do parâmetro de consulta. Não fornecer o documentName na rota ou na consulta pode resultar em comportamento inesperado.

Personalizar o endpoint OpenAPI

Como o documento da OpenAPI é servido através de um endpoint de manipulador de rotas, qualquer personalização disponível para os endpoints mínimos padrão está, portanto, disponível para o endpoint da OpenAPI.

Limitar o acesso a documentos OpenAPI a usuários autorizados

O endpoint OpenAPI não ativa nenhuma verificação de autorização por defeito. No entanto, as verificações de autorização podem ser aplicadas ao documento OpenAPI. No código a seguir, o acesso ao documento OpenAPI é limitado àqueles com a função tester:

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 gerado em cache

O documento OpenAPI é regenerado sempre que uma solicitação para o endpoint OpenAPI é enviada. A regeneração permite que os transformadores incorporem o estado dinâmico de aplicação em sua operação. Por exemplo, regenerar uma solicitação com detalhes do contexto HTTP. Quando aplicável, o documento OpenAPI pode ser armazenado em cache para evitar a execução do pipeline de geração de documentos em cada solicitação 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();

app.MapOpenApi()
    .CacheOutput();

app.MapGet("/", () => "Hello world!");

app.Run();

Gere documentos OpenAPI em tempo de compilação

Em aplicações Web típicas, os documentos OpenAPI são gerados em tempo de execução e servidos através de uma solicitação HTTP para o servidor de aplicativos.

Em alguns cenários, é útil gerar o documento OpenAPI durante a etapa de compilação do aplicativo. Esses cenários incluem:

  • Geração de documentação OpenAPI introduzida no controlo de versões.
  • Geração de documentação OpenAPI que é usada para testes de integração baseados em especificações.
  • Geração de documentação OpenAPI que é servida estaticamente a partir do servidor web.

Para adicionar suporte para gerar documentos OpenAPI em tempo de compilação, instale o pacote Microsoft.Extensions.ApiDescription.Server:

Execute o seguinte comando a partir do Console do Gerenciador de Pacotes :

Install-Package Microsoft.Extensions.ApiDescription.Server

Após a instalação, este pacote gerará automaticamente o(s) documento(s) da API aberta associados ao aplicativo durante a compilação e os preencherá no diretório de saída do aplicativo.

$ dotnet build
$ cat bin/Debug/net9.0/{ProjectName}.json

Personalizar a geração de documentos durante a compilação

Modificando o diretório de saída do arquivo Open API gerado

Por padrão, o documento OpenAPI gerado será emitido para o diretório de saída do aplicativo. Para modificar o local do arquivo emitido, defina o caminho de destino na propriedade OpenApiDocumentsDirectory.

<PropertyGroup>
  <OpenApiDocumentsDirectory>./</OpenApiDocumentsDirectory>
</PropertyGroup>

O valor de OpenApiDocumentsDirectory é determinado em relação ao ficheiro de projeto. Usando o valor ./ acima, emitirá o documento OpenAPI no mesmo diretório que o arquivo de projeto.

Modificando o nome do arquivo de saída

Por padrão, o documento OpenAPI gerado terá o mesmo nome que o arquivo de projeto do aplicativo. Para modificar o nome do arquivo emitido, defina o argumento --file-name na propriedade OpenApiGenerateDocumentsOptions.

<PropertyGroup>
  <OpenApiGenerateDocumentsOptions>--file-name my-open-api</OpenApiGenerateDocumentsOptions>
</PropertyGroup>

Selecionando o documento OpenAPI para gerar

Alguns aplicativos podem ser configurados para emitir vários documentos OpenAPI, para várias versões de uma API ou para distinguir entre APIs públicas e internas. Por padrão, o gerador de documentos em tempo de compilação emitirá arquivos para todos os documentos configurados em um aplicativo. Para emitir apenas para um único nome de documento, defina o argumento --document-name na propriedade OpenApiGenerateDocumentsOptions.

<PropertyGroup>
  <OpenApiGenerateDocumentsOptions>--document-name v2</OpenApiGenerateDocumentsOptions>
</PropertyGroup>

Personalizando o comportamento de tempo de execução durante a geração de documentos em tempo de compilação

Funções de geração de documentos OpenAPI durante a construção, iniciando o ponto de entrada das aplicações com uma implementação de servidor fictício. Um servidor fictício é necessário para produzir documentos OpenAPI precisos porque todas as informações no documento OpenAPI não podem ser analisadas estaticamente. Como o ponto de entrada de aplicativos é invocado, qualquer lógica na inicialização de aplicativos é invocada. Isso inclui código que injeta serviços no contêiner DI ou lê da configuração. Em alguns cenários, é necessário restringir os caminhos de código que serão executados quando o ponto de entrada de aplicativos estiver sendo invocado a partir da geração de documentos em tempo de compilação. Esses cenários incluem:

  • Não ler a partir de determinadas cadeias de caracteres de configuração.
  • Não registrar serviços relacionados ao banco de dados.

Para impedir que esses caminhos de código sejam invocados pelo pipeline de geração durante a compilação, eles podem ser condicionados a uma verificação do assembly de entrada:

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 Adiciona serviços .NET Aspire comuns, como descoberta de serviços, resiliência, verificações de integridade e OpenTelemetry.

Corte e AOT nativo

OpenAPI no ASP.NET Core suporta trimming e AOT nativo. As etapas a seguir criam e publicam um aplicativo OpenAPI com corte e AOT nativo:

Crie um novo projeto ASP.NET Core Web API (Native AOT).

dotnet new webapiaot

Adicione o pacote Microsoft.AspNetCore.OpenAPI.

dotnet add package Microsoft.AspNetCore.OpenApi --prerelease

Atualize Program.cs para permitir a geração de documentos OpenAPI.

+ builder.Services.AddOpenApi();

var app = builder.Build();

+ app.MapOpenApi();

Publique o aplicativo.

dotnet publish

APIs mínimas fornecem suporte interno para gerar informações sobre pontos de extremidade numa aplicação por meio do pacote Microsoft.AspNetCore.OpenApi. Expor a definição de OpenAPI gerada por meio de uma interface do usuário visual requer um pacote de terceiros. Para obter informações sobre o suporte para OpenAPI em APIs baseadas em controlador, consulte a versão .NET 9 deste artigo.

O código a seguir é gerado pelo modelo de API da Web mínima do 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);
}

No código anterior destacado:

  • Microsoft.AspNetCore.OpenApi é explicado na próxima seção.
  • AddEndpointsApiExplorer : Configura a aplicação para usar o Explorador de API para descobrir e descrever endpoints com anotações padrão. WithOpenApi substitui as anotações padrão correspondentes geradas pelo API Explorer com aquelas produzidas a partir do pacote Microsoft.AspNetCore.OpenApi.
  • UseSwaggeradiciona o middleware Swagger.
  • 'UseSwaggerUI' habilita uma versão incorporada da ferramenta Swagger UI.
  • WithName: O IEndpointNameMetadata do endpoint é usado para geração de links e é tratado como o ID da operação na especificação OpenAPI do endpoint fornecido.
  • WithOpenApi é explicado mais adiante neste artigo.

Microsoft.AspNetCore.OpenApi pacote NuGet

ASP.NET Core fornece o pacote Microsoft.AspNetCore.OpenApi para interagir com as especificações OpenAPI para endpoints. O pacote atua como um link entre os modelos OpenAPI definidos no pacote Microsoft.AspNetCore.OpenApi e os pontos de extremidade definidos em APIs mínimas. O pacote fornece uma API que examina os parâmetros, respostas e metadados de um endpoint para construir um tipo de anotação OpenAPI que é usado para descrever um endpoint.

Microsoft.AspNetCore.OpenApi é adicionado como PackageReference a um arquivo de projeto:

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

Para usar Swashbuckle.AspNetCore com Microsoft.AspNetCore.OpenApi, é necessário usar Swashbuckle.AspNetCore 6.4.0 ou posterior. Deve utilizar-se Microsoft.OpenApi 1.4.3 ou posterior para tirar partido dos construtores de cópia em chamadas de WithOpenApi.

Adicione anotações OpenAPI aos endpoints via WithOpenApi

Chamar WithOpenApi no ponto de extremidade aumenta os metadados do ponto de extremidade. Esses metadados podem ser:

  • Consumido em pacotes de terceiros como Swashbuckle.AspNetCore.
  • Exibido na interface do usuário do Swagger ou em YAML ou JSON gerados para definir a 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();

Modificar a anotação OpenAPI no WithOpenApi

O método WithOpenApi aceita uma função que pode ser usada para modificar a anotação OpenAPI. Por exemplo, no código a seguir, uma descrição é adicionada ao primeiro parâmetro do ponto de extremidade:

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

Adicionar IDs de operação ao OpenAPI

Os IDs de operação são usados para identificar exclusivamente um determinado ponto de extremidade no OpenAPI. O método de extensão WithName pode ser usado para definir o ID da operação usado para um método.

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

Como alternativa, a propriedade OperationId pode ser definida diretamente na anotação OpenAPI.

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

Adicionar tags à descrição da OpenAPI

OpenAPI suporta o uso de objetos de tag para categorizar operações. Essas tags são normalmente usadas para agrupar operações na interface do usuário do Swagger. Essas tags podem ser adicionadas a uma operação invocando o método WithTags extension no endpoint com as tags desejadas.

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

Como alternativa, a lista de OpenApiTags pode ser definida na anotação OpenAPI através do método de extensão WithOpenApi.

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

Adicionar resumo ou descrição do ponto final

O resumo e a descrição do ponto final podem ser adicionados invocando o método de extensão WithOpenApi. No código a seguir, os resumos são definidos diretamente na anotação 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"
    });

Excluir descrição da OpenAPI

No exemplo a seguir, exclui-se o endpoint /skipme da geração de uma descrição 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();

Marcar uma API como obsoleta

Para marcar um ponto de extremidade como obsoleto, defina a propriedade Deprecated na anotação OpenAPI.

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

Descrever os tipos de resposta

OpenAPI suporta fornecer uma descrição das respostas retornadas de uma API. As APIs mínimas suportam três estratégias para definir o tipo de resposta de um endpoint:

O método de extensão Produces pode ser usado para adicionar metadata Produces a um endpoint. Quando nenhum parâmetro é fornecido, o método de extensão preenche metadados para o tipo de destino sob um código de status 200 e um tipo de conteúdo application/json.

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

O uso de TypedResults na implementação do manipulador de rotas de um ponto de extremidade inclui automaticamente os metadados do tipo de resposta para o ponto de extremidade. Por exemplo, o código a seguir adiciona uma anotação ao endpoint com uma resposta com o código de status 200 e um tipo de conteúdo application/json.

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

Definir respostas para ProblemDetails

Ao definir o tipo de resposta para pontos de extremidade que podem retornar uma resposta ProblemDetails, o método de extensão ProducesProblem, ProducesValidationProblemou TypedResults.Problem pode ser usado para adicionar a anotação apropriada aos metadados do ponto de extremidade. Observe que os métodos de extensão ProducesProblem e ProducesValidationProblem não podem ser usados com grupos de rotas no .NET 8 e anteriores.

Quando não há anotações explícitas fornecidas por uma das estratégias acima, a estrutura tenta determinar um tipo de resposta padrão examinando a assinatura da resposta. Essa resposta padrão é preenchida sob o código de status 200 na definição OpenAPI.

Vários tipos de resposta

Se um ponto de extremidade puder retornar diferentes tipos de resposta em diferentes cenários, você poderá fornecer metadados das seguintes maneiras:

  • Chame o método de extensão Produces várias vezes, conforme mostrado no exemplo a seguir:

    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);
    
  • Use Results<TResult1,TResult2,TResultN> na assinatura e TypedResults no corpo do manipulador, conforme mostrado no exemplo a seguir:

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

    Os tipos de união Results<TResult1,TResult2,TResultN> declaram que um manipulador de rotas retorna vários tipos concretos que implementam IResult, e qualquer um desses tipos que implementa IEndpointMetadataProvider contribuirá para os metadados do endpoint.

    Os tipos de união implementam operadores de conversão implícita. Esses operadores permitem que o compilador converta automaticamente os tipos especificados nos argumentos genéricos em uma instância do tipo união. Esse recurso tem o benefício adicional de fornecer verificação em tempo de compilação de que um manipulador de rotas retorna apenas os resultados que declara que faz. A tentativa de retornar um tipo que não é declarado como um dos argumentos genéricos para Results<TResult1,TResult2,TResultN> resulta em um erro de compilação.

Descrever o corpo e os parâmetros da solicitação

Além de descrever os tipos que são retornados por um ponto de extremidade, OpenAPI também suporta anotar as entradas que são consumidas por uma API. Estes contributos dividem-se em duas categorias:

  • Parâmetros que aparecem no caminho, na cadeia de caracteres de consulta, nos cabeçalhos ou nos cookies
  • Dados transmitidos como parte do corpo da solicitação

A estrutura infere automaticamente os tipos dos parâmetros de solicitação no caminho, na consulta e na cadeia de caracteres do cabeçalho, baseada na assinatura do manipulador de rotas.

Para definir o tipo de entradas transmitidas como o corpo da solicitação, configure as propriedades usando o método de extensão Accepts para definir o tipo de objeto e o tipo de conteúdo esperados pelo manipulador de solicitação. No exemplo a seguir, o endpoint aceita um objeto Todo no corpo da solicitação com um tipo de conteúdo esperado para application/xml.

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

Além do método de extensão Accepts, um tipo de parâmetro pode descrever sua própria anotação implementando a interface IEndpointParameterMetadataProvider. Por exemplo, o seguinte tipo de Todo adiciona uma anotação que requer um corpo de solicitação com um tipo de conteúdo 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"));
    }
}

Quando nenhuma anotação explícita é fornecida, a estrutura tenta determinar o tipo de solicitação padrão se houver um parâmetro de corpo de solicitação no manipulador de ponto de extremidade. A inferência usa a seguinte heurística para produzir a anotação:

  • Os parâmetros do corpo da solicitação que são lidos de um formulário por meio do atributo [FromForm] são descritos com o tipo de conteúdo multipart/form-data.
  • Todos os outros parâmetros do corpo da solicitação são descritos com o tipo de conteúdo application/json.
  • O corpo da solicitação é tratado como opcional se for anulável ou se a propriedade AllowEmpty estiver definida no atributo FromBody.

Suporte a controle de versão de API

APIs mínimas suportam versionamento de API por meio do pacote Asp.Versioning.Http. Exemplos de configuração de controle de versão com APIs mínimas podem ser encontrados em o repositório de controle de versão de API.

ASP.NET Código-fonte OpenAPI principal no GitHub

Recursos adicionais

Um aplicativo de API mínimo pode descrever o de especificação OpenAPI para manipuladores de rotas usando Swashbuckle.

Para obter informações sobre o suporte para OpenAPI em APIs baseadas em controlador, consulte a versão .NET 9 deste artigo.

O código a seguir é um aplicativo ASP.NET Core típico com suporte a 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();

Excluir descrição da OpenAPI

No exemplo a seguir, o ponto de extremidade /skipme é excluído da geração de uma descrição 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();

Descrever os tipos de resposta

O exemplo a seguir usa os tipos de resultado internos para personalizar a resposta:

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

Adicionar ids de operação ao OpenAPI

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

Adicionar tags à descrição da OpenAPI

O código a seguir usa uma tag de agrupamento OpenAPI :

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