Skip to content

Epic: Minimal API - OpenAPI features #34514

@rafikiassumani-msft

Description

@rafikiassumani-msft

This issue covers the desired experience for minimal APIs integration with OpenAPI via metadata and ApiExplorer observing libraries like Swashbuckle and nSwag.

Issues (ASP.NET Core)

Priority One


Other

Issues (Swashbuckle)

Additional context

The goal is to allow for minimal APIs to support having metadata specified (manually in .NET 6, either imperatively via extension methods or declaratively via attributes, potentially automatically based on endpoint implementation and/or convention in a release after .NET 6) that enables the following to be satisfied by default when an OpenAPI library is also configured (i.e. without the OpenAPI library requiring further manual configuration):

  • Endpoint name that maps to operationId in generated OpenAPI documents.
    • Note the endpoint name is also used when using LinkGenerator to generate URL/links for endpoints
  • Endpoint group name that maps to the document name in generated OpenAPI documents (typically used for versioning, e.g. "v1", "v2")
  • Metadata indicating that the API should be excluded/ignored from OpenAPI document generation
  • Metadata indicating what response types a method produces, where each response is the combination of:
    • One status code
    • One or more content types, e.g. "application/json"
    • An optional schema per content type

Examples

Example of what specifying the metadata imperatively could look like:

app.MapGet("/admin", () => "For admins only")
   .WithName("AdminDetails")
   .RequiresAuthorization("Admins")
   .ExcludeFromApiExplorer();

app.MapPost("/todos", async (Todo todo, TodoDb db) =>
    {
        if (!MinimalValidation.TryValidate(todo, out var errors))
            return Results.ValidationProblem(errors);

        db.Todos.Add(todo);
        await db.SaveChangesAsync();

        return Results.CreatedAtRoute("GetTodoById", new { todo.Id }, todo);
    })
    .WithName("AddTodo")
    .WithGroupName("v1")
    .ProducesValidationProblem()
    .Produces<Todo>(StatusCodes.Status201Created);

Example of what specifying the metadata declaratively could look like:

app.MapGet("/admin", AdminDetails);
app.MapPost("/todos-attr-desc", AddTodo);

[Authorized(Policy = "Admins")]
[ExcludeFromApiExplorer]
string AdminDetails()
{
    return "For admins only";
}

[EndpointGroupName("v1")]
[ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest, "application/problem+json")]
[ProducesResponseType(typeof(Todo), StatusCodes.Status201Created)]
async Task<IResult> AddTodo(Todo todo, TodoDb db)
{
    if (!MinimalValidation.TryValidate(todo, out var errors))
        return Results.ValidationProblem(errors);

    db.Todos.Add(todo);
    await db.SaveChangesAsync();

    return Results.Created($"/todos/{todo.Id}", todo);
}

Metadata

Metadata

Labels

EpicGroups multiple user stories. Can be grouped under a theme.area-minimalIncludes minimal APIs, endpoint filters, parameter binding, request delegate generator etcfeature-minimal-actionsController-like actions for endpoint routing

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions