Skip to content

Commit 9629ac9

Browse files
authored
Merge pull request #35212 from dotnet/main
2 parents f39fcdd + 5694813 commit 9629ac9

File tree

20 files changed

+816
-4
lines changed

20 files changed

+816
-4
lines changed

aspnetcore/blazor/host-and-deploy/configure-trimmer.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,9 @@ To configure the IL Trimmer, see the [Trimming options](/dotnet/core/deploying/t
3333
The default trimmer granularity for Blazor apps is `partial`. To trim all assemblies, change the granularity to `full` in the app's project file:
3434

3535
```xml
36-
<ItemGroup>
36+
<PropertyGroup>
3737
<TrimMode>full</TrimMode>
38-
</ItemGroup>
38+
</PropertyGroup>
3939
```
4040

4141
For more information, see [Trimming options (.NET documentation)](/dotnet/core/deploying/trimming/trimming-options#trimming-granularity).
662 KB
Loading
Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
---
2+
title: ASP.NET Core OpenAPI XML documentation comment support in ASP.NET Core
3+
author: captainsafia
4+
description: Learn how to integrate XML documentation comments on types by OpenAPI document generation in ASP.NET Core.
5+
ms.author: safia
6+
monikerRange: '>= aspnetcore-10.0'
7+
ms.custom: mvc
8+
ms.date: 4/12/2025
9+
uid: fundamentals/openapi/aspnet-openapi-xml
10+
---
11+
<!-- backup author: rick-anderson -->
12+
# OpenAPI XML documentation comment support in ASP.NET Core
13+
14+
ASP.NET Core XML documentation processing extracts code comments automatically to populate API documentation, ensuring the code and documentation remain synchronized. Metadata from XML documentation comments is included in the generated OpenAPI document without requiring changes to the app code, as long as the project is configured to generate the XML documentation file. XML documentation comments are automatically detected in the application assembly and referenced assemblies with XML documentation enabled.
15+
16+
ASP.NET Core processes [XML documentation tags](https://learn.microsoft.com/dotnet/csharp/language-reference/xmldoc/recommended-tags) like: `<c>`, `<code>`, `<list>`, `<para>`, `<paramref>`, `<typeparamref>`, `<see>`, and `<seealso>`. For XML documentation tags that use references to other elements, like `<see cref="SomeOtherType">`, the implementation strips out the XML tag and maps the reference to plain text for inclusion in the OpenAPI document.
17+
18+
ASP.NET Core XML documentation processing doesn't affect runtime performance. The source generator processes XML documentation at compile time and caches the results, with minimal runtime overhead when rendering the OpenAPI documentation. Furthermore, the OpenAPI document can be cached at runtime using [output-caching](/aspnet/core/performance/caching/overview#output-caching) to further optimize performance.
19+
20+
This article includes a [sample app](#download10) that demonstrates the [`Microsoft.AspNetCore.OpenApi`](https://www.nuget.org/packages/Microsoft.AspNetCore.OpenApi) package's ability to integrate XML documentation comments on types into OpenAPI documents. The sample app is a minimal ASP.NET Core Web API project to generate OpenAPI documents. The XML documentation comments are used to populate summaries, descriptions, parameter information, and response details in the generated OpenAPI document.
21+
22+
The following image shows the Scalar UI with XML documentation comments integrated into the OpenAPI document of the sample app:
23+
24+
![screenshot of app with XML comments in sclaar UI](~/fundamentals/openapi/_static/screenshot.png)
25+
26+
### Supported XML documentation tags
27+
28+
* [`<summary>`](/dotnet/csharp/language-reference/xmldoc/recommended-tags#summary)
29+
* [`<remarks>`](/dotnet/csharp/language-reference/xmldoc/recommended-tags#remarks)
30+
* [`<param>`](/dotnet/csharp/language-reference/xmldoc/recommended-tags#param)
31+
* [`<returns>`](/dotnet/csharp/language-reference/xmldoc/recommended-tags#returns)
32+
* [`<response>`](/dotnet/csharp/language-reference/xmldoc/recommended-tags#response)
33+
* [`<example>`](/dotnet/csharp/language-reference/xmldoc/recommended-tags#example)
34+
* [`<deprecated>`](/dotnet/csharp/language-reference/xmldoc/recommended-tags#deprecated)
35+
* [`<inheritdoc>`](/dotnet/csharp/language-reference/xmldoc/recommended-tags#inheritdoc)
36+
37+
### Document HTTP responses
38+
39+
Document HTTP responses with the `<response>` tag and the `code` attribute:
40+
41+
:::code language="csharp" source="~/fundamentals/openapi/samples/10.x/aspnet-openapi-xml/api/ProjectBoardApis.cs" id="snippet_1" highlight="6-7":::
42+
43+
<!--```csharp
44+
/// <response code="200">Success response with data</response>
45+
/// <response code="404">Resource not found</response>
46+
```-->
47+
48+
### Add examples
49+
50+
To add examples to documentation, use the [`<example>`](/dotnet/csharp/language-reference/xmldoc/recommended-tags#example) tag for types or the `example` attribute for parameters:
51+
52+
```csharp
53+
/// <example>{"name":"Sample","value":42}</example>
54+
/// <param name="id" example="42">The unique identifier</param>
55+
```
56+
57+
## Customizing XML documentation behavior
58+
59+
The following sections describe how to enable and customize XML documentation support.
60+
61+
### Enable XML documentation in an ASP.NET Core API project
62+
63+
1. Enable XML documentation in the project file:
64+
65+
:::code language="xml" source="~/fundamentals/openapi/samples/10.x/aspnet-openapi-xml/models/Models.csproj" highlight="7":::
66+
67+
2. Use the [AddOpenApi](xref:Microsoft.Extensions.DependencyInjection.OpenApiServiceCollectionExtensions.AddOpenApi*) method in the service configuration. No configuration is needed, the source generator handles the rest.
68+
69+
:::code language="csharp" source="~/fundamentals/openapi/samples/10.x/aspnet-openapi-xml/api/Program.cs" highlight="6":::
70+
71+
The source generator detects all standard overloads:
72+
73+
* [`AddOpenApi()`](xref:Microsoft.Extensions.DependencyInjection.OpenApiServiceCollectionExtensions.AddOpenApi(Microsoft.Extensions.DependencyInjection.IServiceCollection))
74+
* [`AddOpenApi("v1")`](xref:Microsoft.Extensions.DependencyInjection.OpenApiServiceCollectionExtensions.AddOpenApi(Microsoft.Extensions.DependencyInjection.IServiceCollection,System.String))
75+
* [`AddOpenApi(options => {})`](xref:Microsoft.Extensions.DependencyInjection.OpenApiServiceCollectionExtensions.AddOpenApi(Microsoft.Extensions.DependencyInjection.IServiceCollection,System.Action{Microsoft.AspNetCore.OpenApi.OpenApiOptions}))
76+
* [`AddOpenApi("v1", options => {})`](xref:Microsoft.Extensions.DependencyInjection.OpenApiServiceCollectionExtensions.AddOpenApi(Microsoft.Extensions.DependencyInjection.IServiceCollection,System.String,System.Action{Microsoft.AspNetCore.OpenApi.OpenApiOptions}))
77+
78+
Each overload is intercepted to automatically include the XML documentation transformers. The source generator doesn't handle overloads where the `documentName` parameter isn't a literal string expression. For example, the transformer isn't registered in the following scenarios:
79+
80+
```csharp
81+
var documentName = "v1";
82+
builder.Services.AddOpenApi(documentName); // No XML support
83+
```
84+
85+
### Add XML documentation sources
86+
87+
The [`Microsoft.AspNetCore.OpenApi`](https://www.nuget.org/packages/Microsoft.AspNetCore.OpenApi) NuGet package automatically resolves XML documentation comments from:
88+
89+
* The application assembly, when the `GenerateDocumentationFile` property is set. In the [sample app](#download10), the `API` project.
90+
91+
:::code language="xml" source="~/fundamentals/openapi/samples/10.x/aspnet-openapi-xml/models/Models.csproj" highlight="7":::
92+
93+
* Any projects referenced via `ProjectReferences` that have the `GenerateDocumentationFile` property set. In the sample app, the `Models` project:
94+
95+
:::code language="xml" source="~/fundamentals/openapi/samples/10.x/aspnet-openapi-xml/api/Api.csproj" highlight="7,16":::
96+
97+
The implementation discovers XML files statically at compile-time. The `AdditionalFiles` item group specifies additional sources for XML files:
98+
99+
:::code language="xml" source="~/fundamentals/openapi/samples/10.x/aspnet-openapi-xml/api/AdditionalFiles.xml" highlight="7":::
100+
101+
To include XML documentation files from referenced assemblies, add them as `AdditionalFiles` in the project:
102+
103+
```xml
104+
<ItemGroup>
105+
<AdditionalFiles Include="Path/To/AssemblyDoc.xml" />
106+
</ItemGroup>
107+
```
108+
109+
#### Disabling XML documentation support
110+
111+
To turn off XML documentation integration, remove the source generator from the `Analyzers` item group. Removing the source generator prevents it from being used during compilation.
112+
113+
:::code language="xml" source="~/fundamentals/openapi/samples/10.x/aspnet-openapi-xml/api/Api-remove.csproj.xml" highlight="7,19-23":::
114+
115+
<!-- review setting <GenerateDocumentationFile>false</GenerateDocumentationFile> prevents the XML file from being generated. Explain the difference between GenerateDocumentationFile = true and <Analyzer Remove -->
116+
117+
## Source generator implementation
118+
119+
The XML documentation feature is implemented as a source generator. The source generator analyzes XML documentation comments at compile time and injects code that translates these comments into OpenAPI metadata. The [`XmlCommentGenerator`](https://source.dot.net/#Microsoft.AspNetCore.OpenApi.SourceGenerators/XmlCommentGenerator.cs,30eb0aa73ef6306a) extracts XML comments from two sources:
120+
121+
* XML documentation files passed as `AdditionalFiles` via a [`ParseXmlFile`](https://source.dot.net/#Microsoft.AspNetCore.OpenApi.SourceGenerators/XmlCommentGenerator.Parser.cs,f7dff3af661aebc2) implementation.
122+
* XML comments from the target assembly's own code via a [`ParseCompilation`](https://source.dot.net/#Microsoft.AspNetCore.OpenApi.SourceGenerators/XmlCommentGenerator.Parser.cs,45358a4d0fff76ac) implementation.
123+
124+
The distinction between these two sources is important. XML documentation files passed as `AdditionalFiles` are static. XML comments from the target assembly come from Roslyn's <!-- review `XmlDocumentationCommentProvider`--> [XML documentation comments provider](https://github.com/dotnet/roslyn/blob/main/src/Compilers/Core/Portable/MetadataReference/PortableExecutableReference.cs#L48-L62). The XML documentation comments provider enhances functionality for connecting an XML comment to the compilation symbol's that it's associated with. This has implications for the way `<inheritdoc />` resolution happens in the implementation, discussed in the next section.
125+
126+
XML comments are parsed into structured `XmlComment` objects with:
127+
128+
* Summary, description, remarks, returns, value sections.
129+
* Parameter documentation with name, description, examples.
130+
* Response documentation with status codes and descriptions.
131+
* Support for examples and deprecated markers.
132+
133+
### `<inheritdoc/>`
134+
135+
The generator supports [`<inheritdoc>`](/dotnet/csharp/language-reference/xmldoc/recommended-tags#inheritdoc) tags, which inherit documentation *as long as they exist in the compilation assembly*. `<inheritdoc />` tags indicate that comments must be resolved from:
136+
137+
* Base classes
138+
* Implemented interfaces
139+
* Base methods for overrides
140+
141+
When `<inheritdoc />` is placed on a symbol, The source generator:
142+
143+
* Uses its knowledge of the symbol in the compilation to discover base classes and interfaces associated with the symbol.
144+
* Supports resolving them automatically
145+
* Substitutes generic type parameters in inherited documentation comments, preserving type references across inheritance boundaries.
146+
147+
The automatic resolution behavior is currently available for XML documentation comments that exist in the assembly under compilation, and ***not*** XML documentation tags that are in referenced projects or packages. In the later scenario, XML documentation comments:
148+
149+
* Are only presented as text.
150+
* Don't provide a trivial strategy for:
151+
* Associating the text content to compilation symbols.
152+
* Developing an understanding of the inheritance hierarchy associated with the types.
153+
154+
XML documentation comments from `ProjectReferences` are automatically resolved and don't require additional configuration.
155+
156+
<a name="download10"></a>
157+
158+
## Download and run the API sample
159+
160+
<!-- TODO, fix sample link -->
161+
Download the [sample code](https://github.com/dotnet/AspNetCore.Docs/tree/main/aspnetcore/fundamentals/openapi/samples) for this article.
162+
163+
To run the sample, navigate to the `api` directory and enter `dotnet run`.
164+
165+
```dotnetcli
166+
cd api
167+
dotnet run
168+
```
169+
170+
Output similar to the following is displayed:
171+
172+
```dotnetcli
173+
Building...
174+
info: Microsoft.Hosting.Lifetime[14]
175+
Now listening on: http://localhost:5052
176+
info: Microsoft.Hosting.Lifetime[0]
177+
Application started. Press Ctrl+C to shut down.
178+
info: Microsoft.Hosting.Lifetime[0]
179+
Hosting environment: Development
180+
info: Microsoft.Hosting.Lifetime[0]
181+
Content root path: ~/git/aspnet-openapi-xml/api
182+
```
183+
184+
Navigate to [http://localhost:5052/](http://localhost:5052/) to view the Scalar UI for interacting with the app. The Scalar UI includes summaries and descriptions on various elements sourced from XML documentation comments.
185+
186+
## Additional resources
187+
188+
* [Source generator implementation notes](https://github.com/captainsafia/aspnet-openapi-xml#implementation-notes)
189+
* The source generator implementation can be found in the [ASP.NET Core repository](https://github.com/dotnet/aspnetcore/tree/main/src/OpenApi/gen).
190+
* <xref:fundamentals/openapi/aspnetcore-openapi>
191+
* <xref:fundamentals/openapi/using-openapi-documents>
192+
* <xref:fundamentals/openapi/openapi-tools>
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<ItemGroup>
2+
<PackageReference Include="Some.Package" Version="10.0.0"
3+
GeneratePathProperty="true" />
4+
</ItemGroup>
5+
6+
<ItemGroup>
7+
<AdditionalFiles Include="$(PkgSome_Package)/lib/net10.0/Some.Package.xml" />
8+
</ItemGroup>
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<Project Sdk="Microsoft.NET.Sdk.Web">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net10.0</TargetFramework>
5+
<Nullable>enable</Nullable>
6+
<ImplicitUsings>enable</ImplicitUsings>
7+
<GenerateDocumentationFile>true</GenerateDocumentationFile>
8+
</PropertyGroup>
9+
10+
<ItemGroup>
11+
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="10.0.0-preview.2.25161.17" />
12+
<PackageReference Include="Scalar.AspNetCore" Version="2.0.30" />
13+
</ItemGroup>
14+
15+
<ItemGroup>
16+
<ProjectReference Include="..\models\Models.csproj" />
17+
</ItemGroup>
18+
19+
<Target Name="DisableCompileTimeOpenApiXmlGenerator" BeforeTargets="CoreCompile">
20+
<ItemGroup>
21+
<Analyzer Remove="$(PkgMicrosoft_AspNetCore_OpenApi)/analyzers/dotnet/cs/Microsoft.AspNetCore.OpenApi.SourceGenerators.dll" />
22+
</ItemGroup>
23+
</Target>
24+
25+
</Project>
26+
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<Project Sdk="Microsoft.NET.Sdk.Web">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net10.0</TargetFramework>
5+
<Nullable>enable</Nullable>
6+
<ImplicitUsings>enable</ImplicitUsings>
7+
<GenerateDocumentationFile>true</GenerateDocumentationFile>
8+
</PropertyGroup>
9+
10+
<ItemGroup>
11+
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="10.0.0-preview.2.25161.17" />
12+
<PackageReference Include="Scalar.AspNetCore" Version="2.0.30" />
13+
</ItemGroup>
14+
15+
<ItemGroup>
16+
<ProjectReference Include="..\models\Models.csproj" />
17+
</ItemGroup>
18+
19+
</Project>
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
@Api_HostAddress = http://localhost:5052
2+
3+
GET {{Api_HostAddress}}/weatherforecast/
4+
Accept: application/json
5+
6+
### Project Board Endpoints ###
7+
8+
### Get all project boards
9+
GET {{Api_HostAddress}}/api/projectboards
10+
Accept: application/json
11+
12+
### Get project board by ID
13+
GET {{Api_HostAddress}}/api/projectboards/1
14+
Accept: application/json
15+
16+
### Create a new project board
17+
POST {{Api_HostAddress}}/api/projectboards
18+
Content-Type: application/json
19+
20+
{
21+
"name": "Website Redesign",
22+
"description": "Tasks for redesigning the company website"
23+
}
24+
25+
### Update a project board
26+
PUT {{Api_HostAddress}}/api/projectboards/1
27+
Content-Type: application/json
28+
29+
{
30+
"name": "Website Redesign v2",
31+
"description": "Updated tasks for redesigning the company website"
32+
}
33+
34+
### Delete a project board
35+
DELETE {{Api_HostAddress}}/api/projectboards/1
36+
37+
38+
### Todo Endpoints ###
39+
40+
### Get all todos for a project board
41+
GET {{Api_HostAddress}}/api/projectboards/1/todos
42+
Accept: application/json
43+
44+
### Get a specific todo by ID
45+
GET {{Api_HostAddress}}/api/projectboards/1/todos/1
46+
Accept: application/json
47+
48+
### Create a new todo
49+
POST {{Api_HostAddress}}/api/projectboards/1/todos
50+
Content-Type: application/json
51+
52+
{
53+
"title": "Design new homepage",
54+
"description": "Create wireframes for the new homepage design",
55+
"isComplete": false,
56+
"priority": 2,
57+
"dueDate": "2025-03-20T00:00:00Z"
58+
}
59+
60+
### Update a todo
61+
PUT {{Api_HostAddress}}/api/projectboards/1/todos/1
62+
Content-Type: application/json
63+
64+
{
65+
"title": "Design new homepage with feedback",
66+
"description": "Update wireframes based on stakeholder feedback",
67+
"isComplete": true,
68+
"priority": 3,
69+
"dueDate": "2025-03-25T00:00:00Z"
70+
}
71+
72+
### Delete a todo
73+
DELETE {{Api_HostAddress}}/api/projectboards/1/todos/1
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
using Api;
2+
using Scalar.AspNetCore;
3+
4+
var builder = WebApplication.CreateBuilder(args);
5+
6+
builder.Services.AddOpenApi();
7+
8+
var app = builder.Build();
9+
10+
if (app.Environment.IsDevelopment())
11+
{
12+
app.MapOpenApi();
13+
app.MapScalarApiReference();
14+
}
15+
16+
app.Map("/", () => Results.Redirect("/scalar/v1"));
17+
app.MapProjectBoardApis();
18+
app.MapTodoApis();
19+
20+
app.Run();

0 commit comments

Comments
 (0)