Back to Aspnetcore

Generate OpenAPI documents

aspnetcore/fundamentals/openapi/aspnetcore-openapi.md

latest15.9 KB
Original Source

Generate OpenAPI documents

:::moniker range=">= aspnetcore-10.0"

The Microsoft.AspNetCore.OpenApi package provides built-in support for OpenAPI document generation in ASP.NET Core. The package provides the following features:

  • Support for generating OpenAPI version 3.1 documents.
  • Support for JSON Schema draft 2020-12.
  • Support for generating OpenAPI documents at run time and accessing them via an endpoint on the app.
  • Support for "transformer" APIs that allow modifying the generated document.
  • Support for generating multiple OpenAPI documents from a single app.
  • Takes advantage of JSON schema support provided by xref:System.Text.Json?displayProperty=fullName.
  • Compatible with native AoT.

The default OpenAPI version for generated documents is 3.1. The version can be changed by explicitly setting the xref:Microsoft.AspNetCore.OpenApi.OpenApiOptions.OpenApiVersion%2A property of the xref:Microsoft.AspNetCore.OpenApi.OpenApiOptions in the configureOptions delegate parameter of xref:Microsoft.Extensions.DependencyInjection.OpenApiServiceCollectionExtensions.AddOpenApi%2A:

csharp
builder.Services.AddOpenApi(options =>
{
    // Specify the OpenAPI version to use
    options.OpenApiVersion = Microsoft.OpenApi.OpenApiSpecVersion.OpenApi3_0;
});

When generating the OpenAPI document at build time, the OpenAPI version can be selected by setting the --openapi-version in the OpenApiGenerateDocumentsOptions MSBuild item.

xml
<!-- Configure build-time OpenAPI generation to produce an OpenAPI 3.1 document -->
<OpenApiGenerateDocumentsOptions>--openapi-version OpenApi3_1</OpenApiGenerateDocumentsOptions>

Package installation

Install the Microsoft.AspNetCore.OpenApi package:

Visual Studio

Run the following command from the Package Manager Console:

powershell
Install-Package Microsoft.AspNetCore.OpenApi

.NET CLI

Run the following command in a command shell opened to the directory that contains the app's project file:

dotnetcli
dotnet add package Microsoft.AspNetCore.OpenApi

Configure OpenAPI document generation

The following code:

[!code-csharp]

Launch the app and navigate to https://localhost:{port}/openapi/v1.json to view the generated OpenAPI document, where the {port} placeholder is the port.

Options to Customize OpenAPI document generation

The following sections demonstrate how to customize OpenAPI document generation.

Generate OpenAPI document in YAML format

The OpenAPI document can be generated in either JSON or YAML format. By default, the OpenAPI document is generated in JSON format. To generate the OpenAPI document in YAML format, specify the endpoint in the xref:Microsoft.AspNetCore.Builder.OpenApiEndpointRouteBuilderExtensions.MapOpenApi%2A call with a ".yaml" or ".yml" suffix, as shown in the following example, where the {documentName} placeholder is the document name:

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

Generating OpenAPI documents in YAML format at build time isn't supported but planned for a future preview.

Customize the OpenAPI document name

Each OpenAPI document in an app has a unique name. The default document name that is registered is v1:

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

The document name can be modified by passing the name as a parameter to the xref:Microsoft.Extensions.DependencyInjection.OpenApiServiceCollectionExtensions.AddOpenApi%2A call:

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

The document name surfaces in several places in the OpenAPI implementation.

When fetching the generated OpenAPI document, the document name is provided as the documentName parameter argument in the request. The following requests resolve the v1 and internal documents.

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

Customize the OpenAPI version of a generated document

By default, OpenAPI document generation creates a document that is compliant with the OpenAPI specification. The following code demonstrates how to modify the default version of the OpenAPI document:

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

Customize the OpenAPI endpoint route

By default, the OpenAPI endpoint registered via a call to xref:Microsoft.AspNetCore.Builder.OpenApiEndpointRouteBuilderExtensions.MapOpenApi%2A exposes the document at the /openapi/{documentName}.json endpoint. The following code demonstrates how to customize the route at which the OpenAPI document is registered:

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

It's possible, but not recommended, to remove the documentName route parameter from the endpoint route. When the documentName route parameter is removed from the endpoint route, the framework attempts to resolve the document name from the query parameter. Not providing the documentName in either the route or query can result in unexpected behavior.

Customize the OpenAPI endpoint

Because the OpenAPI document is served via a route handler endpoint, any customization that is available to standard minimal endpoints is available to the OpenAPI endpoint.

Limit OpenAPI document access to authorized users

The OpenAPI endpoint doesn't enable authorization checks by default. However, authorization checks can be applied to the OpenAPI document. In the following code, access to the OpenAPI document is limited to users with the tester role:

[!code-csharp]

Cache generated OpenAPI document

The OpenAPI document is regenerated every time a request to the OpenAPI endpoint is sent. Regeneration enables transformers to incorporate dynamic app state into their operation. For example, regenerating a request with details of the HTTP context. When applicable, the OpenAPI document can be cached to avoid executing the document generation pipeline on each HTTP request.

[!code-csharp]

Generate multiple OpenAPI documents

In some scenarios, it's helpful to generate multiple OpenAPI documents with different content from a single ASP.NET Core API app. These scenarios include generating OpenAPI documentation for different:

  • Audiences, such as public and internal APIs.
  • Versions of an API.
  • Parts of an app, such as a frontend and backend API.

To generate multiple OpenAPI documents, call the xref:Microsoft.Extensions.DependencyInjection.OpenApiServiceCollectionExtensions.AddOpenApi%2A extension method once for each document, specifying a different document name in the first parameter each time.

csharp
builder.Services.AddOpenApi("v1");
builder.Services.AddOpenApi("v2");

Each invocation of xref:Microsoft.Extensions.DependencyInjection.OpenApiServiceCollectionExtensions.AddOpenApi%2A can specify its own set of options, so you can choose to use the same or different customizations for each OpenAPI document.

The framework uses the xref:Microsoft.AspNetCore.OpenApi.OpenApiOptions.ShouldInclude delegate method of xref:Microsoft.AspNetCore.OpenApi.OpenApiOptions to determine which endpoints to include in each document.

For each document, the xref:Microsoft.AspNetCore.OpenApi.OpenApiOptions.ShouldInclude delegate method is called for each endpoint in the app, passing the xref:Microsoft.AspNetCore.Mvc.ApiExplorer.ApiDescription object for the endpoint. The method returns a boolean value indicating whether the endpoint should be included in the document. The xref:Microsoft.AspNetCore.Mvc.ApiExplorer.ApiDescription object:

  • Contains information about the endpoint, such as the HTTP method, route, and response types.
  • Metadata attached to the endpoint via attributes or extension methods.

The default implementation of this delegate uses the xref:Microsoft.AspNetCore.Mvc.ApiExplorer.ApiDescription.GroupName field of xref:Microsoft.AspNetCore.Mvc.ApiExplorer.ApiDescription. The delegate is set on an endpoint using either the xref:Microsoft.AspNetCore.Builder.RoutingEndpointConventionBuilderExtensions.WithGroupName%2A extension method or the xref:Microsoft.AspNetCore.Routing.EndpointGroupNameAttribute attribute. WithGroupName or the EndpointGroupName attribute determines which endpoints to include in the document. Any endpoint that hasn't been assigned a group name is included all OpenAPI documents.

csharp
// Include endpoints without a group name or with a group name
// that matches the document name
ShouldInclude = (description) => description.GroupName == null || 
    description.GroupName == DocumentName;    

You can customize the xref:Microsoft.AspNetCore.OpenApi.OpenApiOptions.ShouldInclude delegate method to include or exclude endpoints based on any criteria.

Generate OpenAPI documents at build time

[!NOTE] Starting with .NET 9, ASP.NET Core includes built-in OpenAPI support. The Microsoft.AspNetCore.OpenApi package provides OpenAPI document generation at runtime, and adding the Microsoft.Extensions.ApiDescription.Server package enables build-time document generation.

ASP.NET Core generates OpenAPI documents only. Interactive UIs such as Swagger UI or Scalar are not included by default and must be added separately. For guidance on using these UI options, see xref:fundamentals/openapi/using-openapi-documents.

In typical web apps, OpenAPI documents are generated at runtime and served via an HTTP request to the app server.

In some scenarios, it's helpful to generate the OpenAPI document during the app's build step. These scenarios include generating OpenAPI documentation that is:

  • Committed into source control.
  • Used for spec-based integration testing.
  • Served statically from the web server.

To add support for generating OpenAPI documents at build time, install the Microsoft.Extensions.ApiDescription.Server package:

Visual Studio

Run the following command from the Package Manager Console:

powershell
Install-Package Microsoft.Extensions.ApiDescription.Server

.NET CLI

Run the following command in a command shell opened to the directory that contains the app's project file:

dotnetcli
dotnet add package Microsoft.Extensions.ApiDescription.Server

Upon installation, this package:

  • Automatically generates the Open API documents associated with the app during build.
  • Populates the Open API documents in the app's output directory.

If multiple documents are registered and the document name is not v1, the project name is post-fixed with the document name. Example: {ProjectName}_{DocumentName}.json. The {ProjectName} placeholder is the project name, and the {DocumentName} placeholder is the document name.

Visual Studio Code

powershell
dotnet build
type obj\{ProjectName}.json

.NET CLI

cli
dotnet build
cat obj/{ProjectName}.json

View build-time OpenAPI logs (Terminal Logger)

When Microsoft.Extensions.ApiDescription.Server runs the :::no-loc text="GetDocument"::: step during dotnet build, progress messages aren't visible with the .NET Terminal Logger at default verbosity in .NET 8 or later. To surface these messages while building, use either of the following options with the dotnet build command.

Set the Terminal Logger's verbosity with the -tlp option set to v=d (verbosity = detailed):

dotnetcli
dotnet build -tlp:v=d

Disable the Terminal Logger and use legacy-style logs with the --tl option set to off:

dotnetcli
dotnet build --tl:off

Customize build-time document generation

Modify the output directory of the generated Open API file

By default, the generated OpenAPI document is emitted to the app's output directory. To modify the location of the emitted file, set the target path in the OpenApiDocumentsDirectory property:

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

The value of OpenApiDocumentsDirectory is resolved relative to the project file. Using the . value, as seen in the preceding example, emits the OpenAPI document in the same directory as the project file.

Modify the output file name

By default, the generated OpenAPI document has the same name as the app's project file. To modify the name of the emitted file, set the --file-name argument in the OpenApiGenerateDocumentsOptions property:

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

Select the OpenAPI document to generate

Some apps may be configured to emit multiple OpenAPI documents. Multiple OpenAPI documents may be generated for different versions of an API or to distinguish between public and internal APIs. By default, the build-time document generator emits files for all documents that are configured in an app. To only emit for a single document name, set the --document-name argument in the OpenApiGenerateDocumentsOptions property:

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

Customize runtime behavior during build-time document generation

Build-time OpenAPI document generation functions by launching the apps entrypoint with a mock server implementation. A mock server is required to produce accurate OpenAPI documents because all information in the OpenAPI document can't be statically analyzed. Because the apps entrypoint is invoked, any logic in the apps startup is invoked. This includes code that injects services into the DI container or reads from configuration. In some scenarios, it's necessary to restrict the code paths when the app's entry point is invoked from build-time document generation. These scenarios include:

  • Not reading from certain configuration strings.
  • Not registering database-related services.

In order to restrict invoking these code paths by the build-time generation pipeline, they can be conditioned behind a check of the entry assembly:

:::code language="csharp" source="~/fundamentals/openapi/samples/9.x/AspireApp1/AspireApp1.Web/Program.cs" highlight="5-8":::

AddServiceDefaults adds common Aspire services such as service discovery, resilience, health checks, and OpenTelemetry.

Trimming and Native AOT

OpenAPI in ASP.NET Core supports trimming and native AOT. The following steps create and publish an OpenAPI app with trimming and native AOT.

Create a new ASP.NET Core Web API (Native AOT) project:

console
dotnet new webapiaot

Publish the app:

console
dotnet publish

:::moniker-end

[!INCLUDE]

[!INCLUDE]