Skip to content

Commit 24123e8

Browse files
OpenApi 3.1 /1 (#35241)
* OpenApi 3.1 /1 * OpenApi 3.1 /1
1 parent 0ba3006 commit 24123e8

File tree

2 files changed

+277
-23
lines changed

2 files changed

+277
-23
lines changed

aspnetcore/fundamentals/openapi/aspnetcore-openapi.md

Lines changed: 5 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ uid: fundamentals/openapi/aspnetcore-openapi
1010
---
1111
# Generate OpenAPI documents
1212

13-
:::moniker range=">= aspnetcore-9.0"
13+
:::moniker range=">= aspnetcore-10.0"
1414

1515
The [`Microsoft.AspNetCore.OpenApi`](https://www.nuget.org/packages/Microsoft.AspNetCore.OpenApi) package provides built-in support for OpenAPI document generation in ASP.NET Core. The package provides the following features:
1616

@@ -259,32 +259,14 @@ Create a new ASP.NET Core Web API (Native AOT) project.
259259
dotnet new webapiaot
260260
```
261261

262-
:::moniker-end
263-
264-
:::moniker range="= aspnetcore-9.0"
265-
266-
Add the Microsoft.AspNetCore.OpenAPI package.
267-
268-
```console
269-
dotnet add package Microsoft.AspNetCore.OpenApi
270-
```
271-
272-
Update `Program.cs` to enable generating OpenAPI documents.
273-
274-
```diff
275-
+ builder.Services.AddOpenApi();
276-
277-
var app = builder.Build();
278-
279-
+ app.MapOpenApi();
280-
```
281-
282-
:::moniker-end
283-
284262
Publish the app.
285263

286264
```console
287265
dotnet publish
288266
```
289267

268+
:::moniker-end
269+
290270
[!INCLUDE[](~/fundamentals/openapi/includes/aspnetcore-openapi6-8.md)]
271+
272+
[!INCLUDE[](~/fundamentals/openapi/includes/aspnetcore-openapi9.md)]
Lines changed: 272 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,272 @@
1+
:::moniker range="= aspnetcore-9.0"
2+
3+
The [`Microsoft.AspNetCore.OpenApi`](https://www.nuget.org/packages/Microsoft.AspNetCore.OpenApi) package provides built-in support for OpenAPI document generation in ASP.NET Core. The package provides the following features:
4+
5+
* Support for generating OpenAPI documents at run time and accessing them via an endpoint on the app.
6+
* Support for "transformer" APIs that allow modifying the generated document.
7+
* Support for generating multiple OpenAPI documents from a single app.
8+
* Takes advantage of JSON schema support provided by [`System.Text.Json`](/dotnet/api/system.text.json).
9+
* Is compatible with native AoT.
10+
11+
## Package installation
12+
13+
Install the `Microsoft.AspNetCore.OpenApi` package:
14+
15+
### [Visual Studio](#tab/visual-studio)
16+
17+
Run the following command from the **Package Manager Console**:
18+
19+
```powershell
20+
Install-Package Microsoft.AspNetCore.OpenApi
21+
```
22+
23+
### [.NET CLI](#tab/net-cli)
24+
25+
Run the following command:
26+
27+
```dotnetcli
28+
dotnet add package Microsoft.AspNetCore.OpenApi
29+
```
30+
---
31+
32+
## Configure OpenAPI document generation
33+
34+
The following code:
35+
36+
* Adds OpenAPI services using the <xref:Microsoft.Extensions.DependencyInjection.OpenApiServiceCollectionExtensions.AddOpenApi%2A> extension method on the app builder's service collection.
37+
* Maps an endpoint for viewing the OpenAPI document in JSON format with the <xref:Microsoft.AspNetCore.Builder.OpenApiEndpointRouteBuilderExtensions.MapOpenApi%2A> extension method on the app.
38+
39+
[!code-csharp[](~/fundamentals/openapi/samples/9.x/WebMinOpenApi/Program.cs?name=snippet_first&highlight=3,9)]
40+
41+
Launch the app and navigate to `https://localhost:<port>/openapi/v1.json` to view the generated OpenAPI document.
42+
43+
## Options to Customize OpenAPI document generation
44+
45+
The following sections demonstrate how to customize OpenAPI document generation.
46+
47+
### Customize the OpenAPI document name
48+
49+
Each OpenAPI document in an app has a unique name. The default document name that is registered is `v1`.
50+
51+
```csharp
52+
builder.Services.AddOpenApi(); // Document name is v1
53+
```
54+
55+
The document name can be modified by passing the name as a parameter to the <xref:Microsoft.Extensions.DependencyInjection.OpenApiServiceCollectionExtensions.AddOpenApi%2A> call.
56+
57+
```csharp
58+
builder.Services.AddOpenApi("internal"); // Document name is internal
59+
```
60+
61+
The document name surfaces in several places in the OpenAPI implementation.
62+
63+
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.
64+
65+
```bash
66+
GET http://localhost:5000/openapi/v1.json
67+
GET http://localhost:5000/openapi/internal.json
68+
```
69+
70+
### Customize the OpenAPI version of a generated document
71+
72+
By default, OpenAPI document generation creates a document that is compliant with [v3.0 of the OpenAPI specification](https://spec.openapis.org/oas/v3.0.0). The following code demonstrates how to modify the default version of the OpenAPI document:
73+
74+
```csharp
75+
builder.Services.AddOpenApi(options =>
76+
{
77+
options.OpenApiVersion = OpenApiSpecVersion.OpenApi2_0;
78+
});
79+
```
80+
81+
### Customize the OpenAPI endpoint route
82+
83+
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:
84+
85+
```csharp
86+
app.MapOpenApi("/openapi/{documentName}/openapi.json");
87+
```
88+
89+
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.
90+
91+
### Customize the OpenAPI endpoint
92+
93+
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.
94+
95+
#### Limit OpenAPI document access to authorized users
96+
97+
The OpenAPI endpoint doesn't enable any 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 those with the `tester` role:
98+
99+
[!code-csharp[](~/fundamentals/openapi/samples/9.x/WebMinOpenApi/Program.cs?name=snippet_mapopenapiwithauth)]
100+
101+
#### Cache generated OpenAPI document
102+
103+
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.
104+
105+
[!code-csharp[](~/fundamentals/openapi/samples/9.x/WebMinOpenApi/Program.cs?name=snippet_mapopenapiwithcaching)]
106+
107+
## Generate multiple OpenAPI documents
108+
109+
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:
110+
111+
* Generating OpenAPI documentation for different audiences, such as public and internal APIs.
112+
* Generating OpenAPI documentation for different versions of an API.
113+
* Generating OpenAPI documentation for different parts of an app, such as a frontend and backend API.
114+
115+
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.
116+
117+
```csharp
118+
builder.Services.AddOpenApi("v1");
119+
builder.Services.AddOpenApi("v2");
120+
```
121+
122+
Each invocation of <xref:Microsoft.Extensions.DependencyInjection.OpenApiServiceCollectionExtensions.AddOpenApi%2A> can specify its own set of options, so that you can choose to use the same or different customizations for each OpenAPI document.
123+
124+
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.
125+
126+
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:
127+
128+
* contains information about the endpoint, such as the HTTP method, route, and response types
129+
* Metadata attached to the endpoint via attributes or extension methods.
130+
131+
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 has not been assigned a group name is included all OpenAPI documents.
132+
133+
```csharp
134+
// Include endpoints without a group name or with a group name that matches the document name
135+
ShouldInclude = (description) => description.GroupName == null || description.GroupName == DocumentName;
136+
```
137+
138+
You can customize the <xref:Microsoft.AspNetCore.OpenApi.OpenApiOptions.ShouldInclude> delegate method to include or exclude endpoints based on any criteria you choose.
139+
140+
## Generate OpenAPI documents at build-time
141+
142+
In typical web apps, OpenAPI documents are generated at run-time and served via an HTTP request to the app server.
143+
144+
In some scenarios, it's helpful to generate the OpenAPI document during the app's build step. These scenarios include:
145+
146+
* Generating OpenAPI documentation that is committed into source control.
147+
* Generating OpenAPI documentation that is used for spec-based integration testing.
148+
* Generating OpenAPI documentation that is served statically from the web server.
149+
150+
To add support for generating OpenAPI documents at build time, install the `Microsoft.Extensions.ApiDescription.Server` package:
151+
152+
### [Visual Studio](#tab/visual-studio)
153+
154+
Run the following command from the **Package Manager Console**:
155+
156+
```powershell
157+
Install-Package Microsoft.Extensions.ApiDescription.Server
158+
```
159+
160+
### [.NET CLI](#tab/net-cli)
161+
162+
Run the following command in the directory that contains the project file:
163+
164+
```dotnetcli
165+
dotnet add package Microsoft.Extensions.ApiDescription.Server
166+
```
167+
168+
---
169+
170+
Upon installation, this package:
171+
172+
* Automatically generates the Open API document(s) associated with the app during build.
173+
* Populates the Open API documents in the app's output directory.
174+
175+
If multiple documents are registered, ***and*** document name is ***not*** `v1`, it's post-fixed with the document name. E.g., `{ProjectName}_{DocumentName}.json`.
176+
177+
# [Visual Studio Code](#tab/visual-studio-code)
178+
179+
```powershell
180+
dotnet build
181+
type obj\{ProjectName}.json
182+
```
183+
184+
# [.NET Core CLI](#tab/netcore-cli)
185+
186+
```cli
187+
dotnet build
188+
cat obj/{ProjectName}.json
189+
```
190+
191+
---
192+
193+
### Customizing build-time document generation
194+
195+
#### Modifying the output directory of the generated Open API file
196+
197+
By default, the generated OpenAPI document will be emitted to the app's output directory. To modify the location of the emitted file, set the target path in the `OpenApiDocumentsDirectory` property.
198+
199+
```xml
200+
<PropertyGroup>
201+
<OpenApiDocumentsDirectory>.</OpenApiDocumentsDirectory>
202+
</PropertyGroup>
203+
```
204+
205+
The value of `OpenApiDocumentsDirectory` is resolved relative to the project file. Using the `.` value above will emit the OpenAPI document in the same directory as the project file.
206+
207+
#### Modifying the output file name
208+
209+
By default, the generated OpenAPI document will have 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.
210+
211+
```xml
212+
<PropertyGroup>
213+
<OpenApiGenerateDocumentsOptions>--file-name my-open-api</OpenApiGenerateDocumentsOptions>
214+
</PropertyGroup>
215+
```
216+
217+
#### Selecting the OpenAPI document to generate
218+
219+
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.
220+
221+
```xml
222+
<PropertyGroup>
223+
<OpenApiGenerateDocumentsOptions>--document-name v2</OpenApiGenerateDocumentsOptions>
224+
</PropertyGroup>
225+
```
226+
227+
### Customizing run-time behavior during build-time document generation
228+
229+
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](xref:fundamentals/dependency-injection) or reads from configuration. In some scenarios, it's necessary to restrict the code paths that will run when the apps entry point is being invoked from build-time document generation. These scenarios include:
230+
231+
* Not reading from certain configuration strings.
232+
* Not registering database-related services.
233+
234+
In order to restrict these code paths from being invoked by the build-time generation pipeline, they can be conditioned behind a check of the entry assembly:
235+
236+
:::code language="csharp" source="~/fundamentals/openapi/samples/9.x/AspireApp1/AspireApp1.Web/Program.cs" highlight="5-8":::
237+
238+
[AddServiceDefaults](https://source.dot.net/#TestingAppHost1.ServiceDefaults/Extensions.cs,0f0d863053754768,references)<!--keep--> adds common .NET Aspire services such as service discovery, resilience, health checks, and OpenTelemetry.
239+
240+
## Trimming and Native AOT
241+
242+
OpenAPI in ASP.NET Core supports trimming and native AOT. The following steps create and publish an OpenAPI app with trimming and native AOT:
243+
244+
Create a new ASP.NET Core Web API (Native AOT) project.
245+
246+
```console
247+
dotnet new webapiaot
248+
```
249+
250+
Add the Microsoft.AspNetCore.OpenAPI package.
251+
252+
```console
253+
dotnet add package Microsoft.AspNetCore.OpenApi
254+
```
255+
256+
Update `Program.cs` to enable generating OpenAPI documents.
257+
258+
```diff
259+
+ builder.Services.AddOpenApi();
260+
261+
var app = builder.Build();
262+
263+
+ app.MapOpenApi();
264+
```
265+
266+
:::moniker-end
267+
268+
Publish the app.
269+
270+
```console
271+
dotnet publish
272+
```

0 commit comments

Comments
 (0)