* Mon prep

* Mon prep

* Mon prep

* Mon prep

* Mon prep
pull/32398/head
Rick Anderson 2024-04-24 16:06:18 -10:00 committed by GitHub
parent df0acd9616
commit 814bc426c6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 217 additions and 7 deletions

View File

@ -0,0 +1,209 @@
:::moniker range="> aspnetcore-6.0 < aspnetcore-9.0"
The [OpenAPI specification](https://spec.openapis.org/oas/latest.html) is a programming language-agnostic standard for documenting HTTP APIs. This standard is supported in minimal APIs through a combination of built-in APIs and open-source libraries. There are three key aspects to OpenAPI integration in an application:
* Generating information about the endpoints in the app.
* Gathering the information into a format that matches the OpenAPI schema.
* Exposing the generated OpenAPI schema via a visual UI or a serialized file.
Minimal APIs provide built-in support for generating information about endpoints in an app via the `Microsoft.AspNetCore.OpenApi` package. Exposing the generated OpenAPI definition via a visual UI requires a third-party package.
The following code is generated by the ASP.NET Core minimal web API template and uses OpenAPI:
[!code-csharp[](~/fundamentals/minimal-apis/7.0-samples/WebMinOpenApi/Program.cs?name=snippet&highlight=1,5-6,12-13,35-36)]
In the preceding highlighted code:
* `Microsoft.AspNetCore.OpenApi` is explained in the next section.
* <xref:Microsoft.Extensions.DependencyInjection.EndpointMetadataApiExplorerServiceCollectionExtensions.AddEndpointsApiExplorer%2A> : Configures the app to use the API Explorer to discover and describe endpoints with default annotations. `WithOpenApi` overrides matching, default annotations generated by the API Explorer with those produced from the `Microsoft.AspNetCore.OpenApi` package.
* `UseSwagger`adds the [Swagger middleware](xref:tutorials/get-started-with-swashbuckle#add-and-configure-swagger-middleware).
* `UseSwaggerUI` enables an embedded version of the Swagger UI tool.
* <xref:Microsoft.AspNetCore.Builder.RoutingEndpointConventionBuilderExtensions.WithName%2A>: The <xref:Microsoft.AspNetCore.Routing.IEndpointNameMetadata> on the endpoint is used for link generation and is treated as the operation ID in the given endpoint's OpenAPI specification.
* [`WithOpenApi`](/dotnet/api/microsoft.aspnetcore.builder.openapiendpointconventionbuilderextensions.withopenapi) is explained later in this article.
<a name="openapinuget"></a>
## `Microsoft.AspNetCore.OpenApi` NuGet package
ASP.NET Core provides the [`Microsoft.AspNetCore.OpenApi`](https://www.nuget.org/packages/Microsoft.AspNetCore.OpenApi/) package to interact with OpenAPI specifications for endpoints. The package acts as a link between the OpenAPI models that are defined in the `Microsoft.AspNetCore.OpenApi` package and the endpoints that are defined in Minimal APIs. The package provides an API that examines an endpoint's parameters, responses, and metadata to construct an OpenAPI annotation type that is used to describe an endpoint.
`Microsoft.AspNetCore.OpenApi` is added as a PackageReference to a project file:
[!code-xml[](~/fundamentals/minimal-apis/7.0-samples/WebMinOpenApi/projectFile.xml?highlight=10)]
When using [`Swashbuckle.AspNetCore`](https://www.nuget.org/packages/Swashbuckle.AspNetCore/) with `Microsoft.AspNetCore.OpenApi`, `Swashbuckle.AspNetCore` 6.4.0 or later must be used. [`Microsoft.OpenApi`](https://www.nuget.org/packages/Microsoft.OpenApi/) 1.4.3 or later must be used to leverage copy constructors in `WithOpenApi` invocations.
## Add OpenAPI annotations to endpoints via `WithOpenApi`
Calling [`WithOpenApi`](/dotnet/api/microsoft.aspnetcore.builder.openapiendpointconventionbuilderextensions.withopenapi) on the endpoint adds to the endpoint's metadata. This metadata can be:
* Consumed in third-party packages like [Swashbuckle.AspNetCore](https://www.nuget.org/packages/Swashbuckle.AspNetCore/).
* Displayed in the Swagger user interface or in YAML or JSON generated to define the API.
[!code-csharp[](~/fundamentals/minimal-apis/7.0-samples/todo/Program.cs?name=snippet_withopenapi&highlight=9)]
### Modify the OpenAPI annotation in `WithOpenApi`
The [`WithOpenApi`](/dotnet/api/microsoft.aspnetcore.builder.openapiendpointconventionbuilderextensions.withopenapi) method accepts a function that can be used to modify the OpenAPI annotation. For example, in the following code, a description is added to the first parameter of the endpoint:
[!code-csharp[](~/fundamentals/minimal-apis/7.0-samples/todo/Program.cs?name=snippet_withopenapi2&highlight=9-99)]
## Add operation IDs to OpenAPI
Operation IDs are used to uniquely identify a given endpoint in OpenAPI. The [`WithName`](/dotnet/api/microsoft.aspnetcore.builder.routingendpointconventionbuilderextensions.withname) extension method can be used to set the operation ID used for a method.
[!code-csharp[](~/fundamentals/minimal-apis/samples/todo/Program.cs?name=snippet_name)]
Alternatively, the `OperationId` property can be set directly on the OpenAPI annotation.
```csharp
app.MapGet("/todos", async (TodoDb db) => await db.Todos.ToListAsync())
.WithOpenApi(operation => new(operation)
{
OperationId = "GetTodos"
});
```
## Add tags to the OpenAPI description
OpenAPI supports using [tag objects](https://swagger.io/docs/specification/grouping-operations-with-tags/) to categorize operations. These tags are typically used to group operations in the Swagger UI. These tags can be added to an operation by invoking the [WithTags](/dotnet/api/microsoft.aspnetcore.http.openapiroutehandlerbuilderextensions.withtags) extension method on the endpoint with the desired tags.
[!code-csharp[](~/fundamentals/minimal-apis/samples/todo/Program.cs?name=snippet_grp)]
Alternatively, the list of `OpenApiTags` can be set on the OpenAPI annotation via the `WithOpenApi` extension method.
```csharp
app.MapGet("/todos", async (TodoDb db) => await db.Todos.ToListAsync())
.WithOpenApi(operation => new(operation)
{
Tags = new List<OpenApiTag> { new() { Name = "Todos" } }
});
```
## Add endpoint summary or description
The endpoint summary and description can be added by invoking the `WithOpenApi` extension method. In the following code, the summaries are set directly on the OpenAPI annotation.
```csharp
app.MapGet("/todoitems2", async (TodoDb db) => await db.Todos.ToListAsync())
.WithOpenApi(operation => new(operation)
{
Summary = "This is a summary",
Description = "This is a description"
});
```
## Exclude OpenAPI description
In the following sample, the `/skipme` endpoint is excluded from generating an OpenAPI description:
[!code-csharp[](~/fundamentals/minimal-apis/7.0-samples/WebMinAPIs/Program.cs?name=snippet_swag2&highlight=20-21)]
## Mark an API as obsolete
To mark an endpoint as obsolete, set the `Deprecated` property on the OpenAPI annotation.
```csharp
app.MapGet("/todos", async (TodoDb db) => await db.Todos.ToListAsync())
.WithOpenApi(operation => new(operation)
{
Deprecated = true
});
```
## Describe response types
OpenAPI supports providing a description of the responses returned from an API. Minimal APIs support three strategies for setting the response type of an endpoint:
* Via the [`Produces`](/dotnet/api/microsoft.aspnetcore.http.openapiroutehandlerbuilderextensions.produces) extension method on the endpoint
* Via the [`ProducesResponseType`](/dotnet/api/microsoft.aspnetcore.mvc.producesresponsetypeattribute) attribute on the route handler
* By returning [`TypedResults`](/dotnet/api/microsoft.aspnetcore.http.typedresults) from the route handler
The `Produces` extension method can be used to add `Produces` metadata to an endpoint. When no parameters are provided, the extension method populates metadata for the targeted type under a `200` status code and an `application/json` content type.
```csharp
app
.MapGet("/todos", async (TodoDb db) => await db.Todos.ToListAsync())
.Produces<IList<Todo>>();
```
Using [`TypedResults`](/dotnet/api/microsoft.aspnetcore.http.typedresults) in the implementation of an endpoint's route handler automatically includes the response type metadata for the endpoint. For example, the following code automatically annotates the endpoint with a response under the `200` status code with an `application/json` content type.
```csharp
app.MapGet("/todos", async (TodoDb db) =>
{
var todos = await db.Todos.ToListAsync());
return TypedResults.Ok(todos);
});
```
### Set responses for `ProblemDetails`
When setting the response type for endpoints that may return a ProblemDetails response, the [`ProducesProblem`](/dotnet/api/microsoft.aspnetcore.http.openapiroutehandlerbuilderextensions.producesproblem) extension method or [`TypedResults.Problem`](/dotnet/api/microsoft.aspnetcore.http.typedresults.problem?) can be used to add the appropriate annotation to the endpoint's metadata.
When there are no explicit annotations provided by one of the strategies above, the framework attempts to determine a default response type by examining the signature of the response. This default response is populated under the `200` status code in the OpenAPI definition.
### Multiple response types
If an endpoint can return different response types in different scenarios, you can provide metadata in the following ways:
* Call the [`Produces`](/dotnet/api/microsoft.aspnetcore.http.openapiroutehandlerbuilderextensions.produces) extension method multiple times, as shown in the following example:
[!code-csharp[](~/fundamentals/minimal-apis/samples/todo/Program.cs?name=snippet_getCustom)]
* Use [`Results<TResult1,TResult2,TResultN>`](xref:Microsoft.AspNetCore.Http.HttpResults.Results%606) in the signature and [`TypedResults`](/dotnet/api/microsoft.aspnetcore.http.typedresults) in the body of the handler, as shown in the following example:
:::code language="csharp" source="~/../AspNetCore.Docs.Samples/fundamentals/minimal-apis/samples/MultipleResultTypes/Program.cs" id="snippet_multiple_result_types":::
The `Results<TResult1,TResult2,TResultN>` [union types](https://en.wikipedia.org/wiki/Union_type) declare that a route handler returns multiple `IResult`-implementing concrete types, and any of those types that implement `IEndpointMetadataProvider` will contribute to the endpoints metadata.
The union types implement implicit cast operators. These operators enable the compiler to automatically convert the types specified in the generic arguments to an instance of the union type. This capability has the added benefit of providing compile-time checking that a route handler only returns the results that it declares it does. Attempting to return a type that isn't declared as one of the generic arguments to `Results<TResult1,TResult2,TResultN>` results in a compilation error.
## Describe request body and parameters
In addition to describing the types that are returned by an endpoint, OpenAPI also supports annotating the inputs that are consumed by an API. These inputs fall into two categories:
* Parameters that appear in the path, query string, headers, or cookies
* Data transmitted as part of the request body
The framework infers the types for request parameters in the path, query, and header string automatically based on the signature of the route handler.
To define the type of inputs transmitted as the request body, configure the properties by using the [`Accepts`](/dotnet/api/microsoft.aspnetcore.http.openapiroutehandlerbuilderextensions.accepts) extension method to define the object type and content type that are expected by the request handler. In the following example, the endpoint accepts a `Todo` object in the request body with an expected content-type of `application/xml`.
```csharp
app.MapPost("/todos/{id}", (int id, Todo todo) => ...)
.Accepts<Todo>("application/xml");
```
In addition to the [`Accepts`](/dotnet/api/microsoft.aspnetcore.http.openapiroutehandlerbuilderextensions.accepts) extension method, A parameter type can describe its own annotation by implementing the [`IEndpointParameterMetadataProvider`](/dotnet/api/microsoft.aspnetcore.http.metadata.iendpointparametermetadataprovider) interface. For example, the following `Todo` type adds an annotation that requires a request body with an `application/xml` content-type.
```csharp
public class Todo : IEndpointParameterMetadataProvider
{
public static void PopulateMetadata(ParameterInfo parameter, EndpointBuilder builder)
{
builder.Metadata.Add(new ConsumesAttribute(typeof(Todo), isOptional: false, "application/xml"));
}
}
```
When no explicit annotation is provided, the framework attempts to determine the default request type if there's a request body parameter in the endpoint handler. The inference uses the following heuristics to produce the annotation:
* Request body parameters that are read from a form via the [`[FromForm]`](/dotnet/api/microsoft.aspnetcore.mvc.fromformattribute) attribute are described with the `multipart/form-data` content-type.
* All other request body parameters are described with the `application/json` content-type.
* The request body is treated as optional if it's nullable or if the [`AllowEmpty`](/dotnet/api/microsoft.aspnetcore.mvc.frombodyattribute.microsoft-aspnetcore-http-metadata-ifrombodymetadata-allowempty) property is set on the [`FromBody`](/dotnet/api/microsoft.aspnetcore.mvc.frombodyattribute) attribute.
## Support API versioning
Minimal APIs support API versioning via the [Asp.Versioning.Http package](https://www.nuget.org/packages/Asp.Versioning.Http). Examples of configuring versioning with minimal APIs can be found in [the API versioning repo](https://github.com/dotnet/aspnet-api-versioning/tree/3857a332057d970ad11bac0edfdbff8a559a215d/examples/AspNetCore/WebApi).
## ASP.NET Core OpenAPI source code on GitHub
* [`WithOpenApi`](https://github.com/dotnet/aspnetcore/blob/8a4b4deb09c04134f22f8d39aae21d212282004f/src/OpenApi/src/OpenApiRouteHandlerBuilderExtensions.cs)
* [OpenApiGenerator](https://github.com/dotnet/aspnetcore/blob/main/src/OpenApi/src/OpenApiGenerator.cs)
## Additional Resources
* <xref:fundamentals/minimal-apis/security>
:::moniker-end

View File

@ -4,13 +4,13 @@ author: rick-anderson
description: Learn how to use OpenAPI (Swagger and Swashbuckle) features of minimal APIs in ASP.NET Core.
ms.author: riande
monikerRange: '>= aspnetcore-6.0'
ms.date: 10/24/2022
ms.date: 4/24/2024
uid: fundamentals/minimal-apis/openapi
---
# OpenAPI support in minimal API apps
:::moniker range=">= aspnetcore-7.0"
:::moniker range=">= aspnetcore-9.0"
The [OpenAPI specification](https://spec.openapis.org/oas/latest.html) is a programming language-agnostic standard for documenting HTTP APIs. This standard is supported in minimal APIs through a combination of built-in APIs and open-source libraries. There are three key aspects to OpenAPI integration in an application:
@ -22,7 +22,7 @@ Minimal APIs provide built-in support for generating information about endpoints
The following code is generated by the ASP.NET Core minimal web API template and uses OpenAPI:
[!code-csharp[](7.0-samples/WebMinOpenApi/Program.cs?name=snippet&highlight=1,5-6,12-13,35-36)]
[!code-csharp[](~/fundamentals/minimal-apis/7.0-samples/WebMinOpenApi/Program.cs?name=snippet&highlight=1,5-6,12-13,35-36)]
In the preceding highlighted code:
@ -41,7 +41,7 @@ ASP.NET Core provides the [`Microsoft.AspNetCore.OpenApi`](https://www.nuget.org
`Microsoft.AspNetCore.OpenApi` is added as a PackageReference to a project file:
[!code-xml[](7.0-samples/WebMinOpenApi/projectFile.xml?highlight=10)]
[!code-xml[](~/fundamentals/minimal-apis/7.0-samples/WebMinOpenApi/projectFile.xml?highlight=10)]
When using [`Swashbuckle.AspNetCore`](https://www.nuget.org/packages/Swashbuckle.AspNetCore/) with `Microsoft.AspNetCore.OpenApi`, `Swashbuckle.AspNetCore` 6.4.0 or later must be used. [`Microsoft.OpenApi`](https://www.nuget.org/packages/Microsoft.OpenApi/) 1.4.3 or later must be used to leverage copy constructors in `WithOpenApi` invocations.
@ -52,13 +52,13 @@ Calling [`WithOpenApi`](/dotnet/api/microsoft.aspnetcore.builder.openapiendpoint
* Consumed in third-party packages like [Swashbuckle.AspNetCore](https://www.nuget.org/packages/Swashbuckle.AspNetCore/).
* Displayed in the Swagger user interface or in YAML or JSON generated to define the API.
[!code-csharp[](7.0-samples/todo/Program.cs?name=snippet_withopenapi&highlight=9)]
[!code-csharp[](~/fundamentals/minimal-apis/7.0-samples/todo/Program.cs?name=snippet_withopenapi&highlight=9)]
### Modify the OpenAPI annotation in `WithOpenApi`
The [`WithOpenApi`](/dotnet/api/microsoft.aspnetcore.builder.openapiendpointconventionbuilderextensions.withopenapi) method accepts a function that can be used to modify the OpenAPI annotation. For example, in the following code, a description is added to the first parameter of the endpoint:
[!code-csharp[](7.0-samples/todo/Program.cs?name=snippet_withopenapi2&highlight=9-99)]
[!code-csharp[](~/fundamentals/minimal-apis/7.0-samples/todo/Program.cs?name=snippet_withopenapi2&highlight=9-99)]
## Add operation IDs to OpenAPI
@ -109,7 +109,7 @@ app.MapGet("/todoitems2", async (TodoDb db) => await db.Todos.ToListAsync())
In the following sample, the `/skipme` endpoint is excluded from generating an OpenAPI description:
[!code-csharp[](7.0-samples/WebMinAPIs/Program.cs?name=snippet_swag2&highlight=20-21)]
[!code-csharp[](~/fundamentals/minimal-apis/7.0-samples/WebMinAPIs/Program.cs?name=snippet_swag2&highlight=20-21)]
## Mark an API as obsolete
@ -220,4 +220,5 @@ Minimal APIs support API versioning via the [Asp.Versioning.Http package](https:
:::moniker-end
[!INCLUDE[](~/fundamentals/minimal-apis/includes/openapi8.md)]
[!INCLUDE[](~/fundamentals/minimal-apis/includes/openapi6.md)]