Skip to content

Commit 5f8f891

Browse files
authored
Update WithOpenApi docs and scrub description IDs (#55924)
1 parent 399a5ed commit 5f8f891

10 files changed

+82
-39
lines changed

src/OpenApi/src/Extensions/OpenApiEndpointConventionBuilderExtensions.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ public static class OpenApiEndpointConventionBuilderExtensions
2424
/// Adds an OpenAPI annotation to <see cref="Endpoint.Metadata" /> associated
2525
/// with the current endpoint.
2626
/// </summary>
27+
/// <remarks>
28+
/// This method does not integrate with built-in OpenAPI document generation support in ASP.NET Core
29+
/// and is primarily intended for consumption along-side Swashbuckle.AspNetCore.
30+
/// </remarks>
2731
/// <param name="builder">The <see cref="IEndpointConventionBuilder"/>.</param>
2832
/// <returns>A <see cref="IEndpointConventionBuilder"/> that can be used to further customize the endpoint.</returns>
2933
[RequiresDynamicCode(TrimWarningMessage)]
@@ -38,6 +42,10 @@ public static TBuilder WithOpenApi<TBuilder>(this TBuilder builder) where TBuild
3842
/// Adds an OpenAPI annotation to <see cref="Endpoint.Metadata" /> associated
3943
/// with the current endpoint and modifies it with the given <paramref name="configureOperation"/>.
4044
/// </summary>
45+
/// <remarks>
46+
/// This method does not integrate with built-in OpenAPI document generation support in ASP.NET Core
47+
/// and is primarily intended for consumption along-side Swashbuckle.AspNetCore.
48+
/// </remarks>
4149
/// <param name="builder">The <see cref="IEndpointConventionBuilder"/>.</param>
4250
/// <param name="configureOperation">An <see cref="Func{T, TResult}"/> that returns a new OpenAPI annotation given a generated operation.</param>
4351
/// <returns>A <see cref="IEndpointConventionBuilder"/> that can be used to further customize the endpoint.</returns>

src/OpenApi/src/Services/OpenApiConstants.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4+
using Microsoft.OpenApi.Models;
5+
46
namespace Microsoft.AspNetCore.OpenApi;
57

68
internal static class OpenApiConstants
@@ -10,4 +12,18 @@ internal static class OpenApiConstants
1012
internal const string DefaultOpenApiRoute = "/openapi/{documentName}.json";
1113
internal const string DescriptionId = "x-aspnetcore-id";
1214
internal const string DefaultOpenApiResponseKey = "default";
15+
// Since there's a finite set of operation types that can be included in a given
16+
// OpenApiPaths, we can pre-allocate an array of these types and use a direct
17+
// lookup on the OpenApiPaths dictionary to avoid allocating an enumerator
18+
// over the KeyValuePairs in OpenApiPaths.
19+
internal static readonly OperationType[] OperationTypes = [
20+
OperationType.Get,
21+
OperationType.Post,
22+
OperationType.Put,
23+
OperationType.Delete,
24+
OperationType.Options,
25+
OperationType.Head,
26+
OperationType.Patch,
27+
OperationType.Trace
28+
];
1329
}

src/OpenApi/src/Services/OpenApiDocumentService.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ internal sealed class OpenApiDocumentService(
3131
{
3232
private readonly OpenApiOptions _options = optionsMonitor.Get(documentName);
3333
private readonly OpenApiComponentService _componentService = serviceProvider.GetRequiredKeyedService<OpenApiComponentService>(documentName);
34+
private readonly IOpenApiDocumentTransformer _scrubExtensionsTransformer = new ScrubExtensionsTransformer();
3435

3536
private static readonly OpenApiEncoding _defaultFormEncoding = new OpenApiEncoding { Style = ParameterStyle.Form, Explode = true };
3637

@@ -75,6 +76,8 @@ private async Task ApplyTransformersAsync(OpenApiDocument document, Cancellation
7576
var transformer = _options.DocumentTransformers[i];
7677
await transformer.TransformAsync(document, documentTransformerContext, cancellationToken);
7778
}
79+
// Remove `x-aspnetcore-id` extension from operations after all transformers have run.
80+
await _scrubExtensionsTransformer.TransformAsync(document, documentTransformerContext, cancellationToken);
7881
}
7982

8083
// Note: Internal for testing.

src/OpenApi/src/Transformers/DelegateOpenApiDocumentTransformer.cs

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,6 @@ namespace Microsoft.AspNetCore.OpenApi;
99

1010
internal sealed class DelegateOpenApiDocumentTransformer : IOpenApiDocumentTransformer
1111
{
12-
// Since there's a finite set of operation types that can be included in a given
13-
// OpenApiPaths, we can pre-allocate an array of these types and use a direct
14-
// lookup on the OpenApiPaths dictionary to avoid allocating an enumerator
15-
// over the KeyValuePairs in OpenApiPaths.
16-
private static readonly OperationType[] _operationTypes = [
17-
OperationType.Get,
18-
OperationType.Post,
19-
OperationType.Put,
20-
OperationType.Delete,
21-
OperationType.Options,
22-
OperationType.Head,
23-
OperationType.Patch,
24-
OperationType.Trace
25-
];
2612
private readonly Func<OpenApiDocument, OpenApiDocumentTransformerContext, CancellationToken, Task>? _documentTransformer;
2713
private readonly Func<OpenApiOperation, OpenApiOperationTransformerContext, CancellationToken, Task>? _operationTransformer;
2814

@@ -48,9 +34,9 @@ public async Task TransformAsync(OpenApiDocument document, OpenApiDocumentTransf
4834
var documentService = context.ApplicationServices.GetRequiredKeyedService<OpenApiDocumentService>(context.DocumentName);
4935
foreach (var pathItem in document.Paths.Values)
5036
{
51-
for (var i = 0; i < _operationTypes.Length; i++)
37+
for (var i = 0; i < OpenApiConstants.OperationTypes.Length; i++)
5238
{
53-
var operationType = _operationTypes[i];
39+
var operationType = OpenApiConstants.OperationTypes[i];
5440
if (!pathItem.Operations.TryGetValue(operationType, out var operation))
5541
{
5642
continue;
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using Microsoft.OpenApi.Models;
5+
6+
namespace Microsoft.AspNetCore.OpenApi;
7+
8+
/// <summary>
9+
/// A transformer class that removes implementation-specific extension properties
10+
/// from the OpenAPI document.
11+
/// </summary>
12+
internal sealed class ScrubExtensionsTransformer : IOpenApiDocumentTransformer
13+
{
14+
public Task TransformAsync(OpenApiDocument document, OpenApiDocumentTransformerContext context, CancellationToken cancellationToken)
15+
{
16+
foreach (var pathItem in document.Paths.Values)
17+
{
18+
for (var i = 0; i < OpenApiConstants.OperationTypes.Length; i++)
19+
{
20+
var operationType = OpenApiConstants.OperationTypes[i];
21+
if (!pathItem.Operations.TryGetValue(operationType, out var operation))
22+
{
23+
continue;
24+
}
25+
26+
operation.Extensions.Remove(OpenApiConstants.DescriptionId);
27+
}
28+
}
29+
return Task.CompletedTask;
30+
}
31+
}

src/OpenApi/test/Integration/OpenApiDocumentIntegrationTests.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ await Verifier.Verify(GetOpenApiJson(document))
2424
.UseDirectory(SkipOnHelixAttribute.OnHelix()
2525
? Path.Combine(Environment.GetEnvironmentVariable("HELIX_WORKITEM_ROOT"), "Integration", "snapshots")
2626
: "snapshots")
27-
.ScrubLinesContaining(Microsoft.AspNetCore.OpenApi.OpenApiConstants.DescriptionId)
2827
.UseParameters(documentName);
2928
}
3029

src/OpenApi/test/Integration/snapshots/OpenApiDocumentIntegrationTests.VerifyOpenApiDocument_documentName=forms.verified.txt

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
"200": {
3737
"description": "OK"
3838
}
39-
},
39+
}
4040
}
4141
},
4242
"/forms/form-files": {
@@ -73,7 +73,7 @@
7373
"200": {
7474
"description": "OK"
7575
}
76-
},
76+
}
7777
}
7878
},
7979
"/forms/form-file-multiple": {
@@ -124,7 +124,7 @@
124124
"200": {
125125
"description": "OK"
126126
}
127-
},
127+
}
128128
}
129129
},
130130
"/forms/form-todo": {
@@ -207,7 +207,7 @@
207207
"200": {
208208
"description": "OK"
209209
}
210-
},
210+
}
211211
}
212212
},
213213
"/forms/forms-pocos-and-files": {
@@ -271,7 +271,7 @@
271271
"200": {
272272
"description": "OK"
273273
}
274-
},
274+
}
275275
}
276276
},
277277
"/getbyidandname/{id}/{name}": {
@@ -320,7 +320,7 @@
320320
}
321321
}
322322
}
323-
},
323+
}
324324
}
325325
},
326326
"/forms": {
@@ -360,7 +360,7 @@
360360
"200": {
361361
"description": "OK"
362362
}
363-
},
363+
}
364364
}
365365
}
366366
},

src/OpenApi/test/Integration/snapshots/OpenApiDocumentIntegrationTests.VerifyOpenApiDocument_documentName=responses.verified.txt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@
7070
}
7171
}
7272
}
73-
},
73+
}
7474
}
7575
},
7676
"/responses/200-only-xml": {
@@ -111,7 +111,7 @@
111111
}
112112
}
113113
}
114-
},
114+
}
115115
}
116116
},
117117
"/responses/triangle": {
@@ -130,7 +130,7 @@
130130
}
131131
}
132132
}
133-
},
133+
}
134134
}
135135
},
136136
"/responses/shape": {
@@ -172,7 +172,7 @@
172172
}
173173
}
174174
}
175-
},
175+
}
176176
}
177177
},
178178
"/getbyidandname/{id}/{name}": {
@@ -221,7 +221,7 @@
221221
}
222222
}
223223
}
224-
},
224+
}
225225
}
226226
},
227227
"/forms": {
@@ -261,7 +261,7 @@
261261
"200": {
262262
"description": "OK"
263263
}
264-
},
264+
}
265265
}
266266
}
267267
},

src/OpenApi/test/Integration/snapshots/OpenApiDocumentIntegrationTests.VerifyOpenApiDocument_documentName=v1.verified.txt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
}
4848
}
4949
}
50-
},
50+
}
5151
}
5252
},
5353
"/v1/todos": {
@@ -102,7 +102,7 @@
102102
"200": {
103103
"description": "OK"
104104
}
105-
},
105+
}
106106
}
107107
},
108108
"/v1/todos/{id}": {
@@ -168,7 +168,7 @@
168168
}
169169
}
170170
}
171-
},
171+
}
172172
}
173173
},
174174
"/getbyidandname/{id}/{name}": {
@@ -225,7 +225,7 @@
225225
}
226226
}
227227
}
228-
},
228+
}
229229
}
230230
},
231231
"/forms": {
@@ -275,7 +275,7 @@
275275
"200": {
276276
"description": "OK"
277277
}
278-
},
278+
}
279279
}
280280
}
281281
},

src/OpenApi/test/Integration/snapshots/OpenApiDocumentIntegrationTests.VerifyOpenApiDocument_documentName=v2.verified.txt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
}
3232
}
3333
}
34-
},
34+
}
3535
},
3636
"post": {
3737
"tags": [
@@ -41,7 +41,7 @@
4141
"200": {
4242
"description": "OK"
4343
}
44-
},
44+
}
4545
}
4646
},
4747
"/getbyidandname/{id}/{name}": {
@@ -90,7 +90,7 @@
9090
}
9191
}
9292
}
93-
},
93+
}
9494
}
9595
},
9696
"/forms": {
@@ -130,7 +130,7 @@
130130
"200": {
131131
"description": "OK"
132132
}
133-
},
133+
}
134134
}
135135
}
136136
},

0 commit comments

Comments
 (0)