diff --git a/aspnetcore/fundamentals/openapi/aspnetcore-openapi.md b/aspnetcore/fundamentals/openapi/aspnetcore-openapi.md index e3b0f8ce69..a8d7e3aaf6 100644 --- a/aspnetcore/fundamentals/openapi/aspnetcore-openapi.md +++ b/aspnetcore/fundamentals/openapi/aspnetcore-openapi.md @@ -279,21 +279,43 @@ When no explicit annotation is provided, the framework attempts to determine the #### Describe response types - +OpenAPI supports providing a description of the responses returned from an API. ASP.NET Core provides several strategies for setting the response metadata of an endpoint. Response metadata that can be set includes the status code, the type of the response body, and content type(s) of a response. Responses in OpenAPI may have additional metadata, such as description, headers, links, and examples. This additional metadata can be set with a [document transformer](#use-document-transformers) or [operation transformer](#use-operation-transformers). -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: +The specific mechanisms for setting response metadata depend on the type of app being developed. -* Via the extension method on the endpoint. -* Via the [`ProducesResponseType`](xref:Microsoft.AspNetCore.Mvc.ProducesResponseTypeAttribute) attribute on the route handler. -* By returning from the route handler. +##### [Minimal APIs](#tab/minimal-apis) -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. +In Minimal API apps, ASP.NET Core can extract the response metadata added by extension methods on the endpoint, attributes on the route handler, and the return type of the route handler. + +* The extension method can be used on the endpoint to specify the status code, the type of the response body, and content type(s) of a response from an endpoint. +* The or attribute can be used to specify the type of the response body. +* A route handler can be used to return a type that implements to specify the type and content-type(s) of the response body. +* The extension method on the endpoint can be used to specify the status code and content-type(s) of an error response. + +Note that the and extension methods are supported on both and on . This allows, for example, a common set of error responses to be defined for all operations in a group. + +When not specified by one of the preceding strategies, the: +* Status code for the response defaults to 200. +* Schema for the response body can be inferred from the implicit or explicit return type of the endpoint method, for example, from `T` in ; otherwise, it's considered to be unspecified. +* Content-type for the specified or inferred response body is "application/json". + +In Minimal APIs, the extension method and the attribute only set the response metadata for the endpoint. They do not modify or constrain the behavior of the endpoint, which may return a different status code or response body type than specified by the metadata, and the content-type is determined by the return type of the route handler method, irrespective of any content-type specified in attributes or extension methods. + +The extension method can specify an endpoint's response type, with a default status code of 200 and a default content type of `application/json`. The following example illustrates this: ```csharp app.MapGet("/todos", async (TodoDb db) => await db.Todos.ToListAsync()) .Produces>(); ``` +The can be used to add response metadata to an endpoint. Note that the attribute is applied to the route handler method, not the method invocation to create the route, as shown in the following example: + +```csharp +app.MapGet("/todos", + [ProducesResponseType>(200)] + async (TodoDb db) => await db.Todos.ToListAsync()); +``` + Using 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 @@ -304,13 +326,37 @@ app.MapGet("/todos", async (TodoDb db) => }); ``` -##### Set responses for `ProblemDetails` +Only return types that implement create a `responses` entry in the OpenAPI document. The following is a partial list of some of the helper methods that produce a `responses` entry: -When setting the response type for endpoints that may return a ProblemDetails response, the or extension method or can be used to add the appropriate annotation to the endpoint's metadata. +| TypedResults helper method | status code | +| -------------------------- | ----------- | +| Ok() | 200 | +| Created() | 201 | +| CreatedAtRoute() | 201 | +| Accepted() | 202 | +| AcceptedAtRoute() | 202 | +| NoContent() | 204 | +| BadRequest() | 400 | +| ValidationProblem() | 400 | +| NotFound() | 404 | +| Conflict() | 409 | +| UnprocessableEntity() | 422 | -When there are no explicit annotations provided by one of these strategies, 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. +All of these methods except `NoContent` have a generic overload that specifies the type of the response body. -##### Multiple response types +A class can be implemented to set the endpoint metadata and return it from the route handler. + +###### Set responses for `ProblemDetails` + +When setting the response type for endpoints that may return a ProblemDetails response, the following can be used to add the appropriate response metadata for the endpoint: + +* +* extension method. +* with a status code in the (400-499) range. + +For more information on how to configure a Minimal API app to return ProblemDetails responses, see . + +###### Multiple response types If an endpoint can return different response types in different scenarios, you can provide metadata in the following ways: @@ -326,6 +372,43 @@ If an endpoint can return different response types in different scenarios, you c 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` results in a compilation error. +##### [Controllers](#tab/controllers) + +In controller-based apps, ASP.NET Core can extract the response metadata from the action method signature, attributes, and conventions. + +* You can use the or attribute to specify the status code, the type of the response body, and content type(s) of a response from an action method. +* You can use the or attribute to specify the type of the response body. +* You can use the attribute to specify the response body type for the "default" response. +* You can use the attribute to specify the response body type for an error response. However, be aware that this is only complements the status code and content type(s) specified by an attribute with a 4XX status code. + +Only one or attributes may be applied to an action method, but multiple or attributes with different status codes may be applied to a single action method. + +All of the above attributes can be applied to individual action methods or to the controller class where it applies to all action methods in the controller. + +When not specified by an attribute: +* the status code for the response defaults to 200, +* the schema for the response body of 2xx responses may be inferred from the return type of the action method, e.g. from `T` in , but otherwise is considered to be not specified, +* the schema for the response body of 4xx responses is inferred to be a problem details object, +* the schema for the response body of 3xx and 5xx responses is considered to be not specified, +* the content-type for the response body can be inferred from the return type of the action method and the set of output formatters. + +Note that there are no compile-time checks to ensure that the response metadata specified with a attribute is consistent with the actual behavior of the action method, +which may return a different status code or response body type than specified by the metadata. + +In controller-based apps, ASP.NET responds with a ProblemDetails response type when model validation fails or when the action method returns a result with a 4xx or 5xx HTTP status code. Validation errors typically use the 400 status code, so you can use the attribute to specify the error response for an action, as shown in the following example: + +```csharp +[HttpPut("/todos/{id}")] +[ProducesResponseType(StatusCodes.Status200OK, "application/json")] +[ProducesResponseType(StatusCodes.Status201Created, "application/json")] +[ProducesResponseType(StatusCodes.Status400BadRequest, "application/problem+json")] +public async Task> CreateOrReplaceTodo(string id, Todo todo) +``` + +This example also illustrates how to define multiple response types for an action method, including the content type of the response body. + +--- + #### Excluding endpoints from the generated document By default, all endpoints that are defined in an app are documented in the generated OpenAPI file, but endpoints can be excluded from the document using attributes or extension methods.