Skip to content

Add APIs for OpenAPI document transformers #54935

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Apr 8, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions AspNetCore.sln
Original file line number Diff line number Diff line change
Expand Up @@ -1790,6 +1790,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Components.WasmRemoteAuthen
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sample", "src\OpenApi\sample\Sample.csproj", "{6DEC24A8-A166-432F-8E3B-58FFCDA92F52}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.OpenApi.Microbenchmarks", "src\OpenApi\perf\Microsoft.AspNetCore.OpenApi.Microbenchmarks.csproj", "{CF082AD5-E513-4A27-A6C7-3767E04D6205}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -10807,6 +10809,22 @@ Global
{6DEC24A8-A166-432F-8E3B-58FFCDA92F52}.Release|x64.Build.0 = Release|Any CPU
{6DEC24A8-A166-432F-8E3B-58FFCDA92F52}.Release|x86.ActiveCfg = Release|Any CPU
{6DEC24A8-A166-432F-8E3B-58FFCDA92F52}.Release|x86.Build.0 = Release|Any CPU
{CF082AD5-E513-4A27-A6C7-3767E04D6205}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CF082AD5-E513-4A27-A6C7-3767E04D6205}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CF082AD5-E513-4A27-A6C7-3767E04D6205}.Debug|arm64.ActiveCfg = Debug|Any CPU
{CF082AD5-E513-4A27-A6C7-3767E04D6205}.Debug|arm64.Build.0 = Debug|Any CPU
{CF082AD5-E513-4A27-A6C7-3767E04D6205}.Debug|x64.ActiveCfg = Debug|Any CPU
{CF082AD5-E513-4A27-A6C7-3767E04D6205}.Debug|x64.Build.0 = Debug|Any CPU
{CF082AD5-E513-4A27-A6C7-3767E04D6205}.Debug|x86.ActiveCfg = Debug|Any CPU
{CF082AD5-E513-4A27-A6C7-3767E04D6205}.Debug|x86.Build.0 = Debug|Any CPU
{CF082AD5-E513-4A27-A6C7-3767E04D6205}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CF082AD5-E513-4A27-A6C7-3767E04D6205}.Release|Any CPU.Build.0 = Release|Any CPU
{CF082AD5-E513-4A27-A6C7-3767E04D6205}.Release|arm64.ActiveCfg = Release|Any CPU
{CF082AD5-E513-4A27-A6C7-3767E04D6205}.Release|arm64.Build.0 = Release|Any CPU
{CF082AD5-E513-4A27-A6C7-3767E04D6205}.Release|x64.ActiveCfg = Release|Any CPU
{CF082AD5-E513-4A27-A6C7-3767E04D6205}.Release|x64.Build.0 = Release|Any CPU
{CF082AD5-E513-4A27-A6C7-3767E04D6205}.Release|x86.ActiveCfg = Release|Any CPU
{CF082AD5-E513-4A27-A6C7-3767E04D6205}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -11691,6 +11709,7 @@ Global
{433F91E4-E39D-4EB0-B798-2998B3969A2C} = {6126DCE4-9692-4EE2-B240-C65743572995}
{8A021D6D-7935-4AB3-BB47-38D4FF9B0D13} = {6126DCE4-9692-4EE2-B240-C65743572995}
{6DEC24A8-A166-432F-8E3B-58FFCDA92F52} = {2299CCD8-8F9C-4F2B-A633-9BF4DA81022B}
{CF082AD5-E513-4A27-A6C7-3767E04D6205} = {2299CCD8-8F9C-4F2B-A633-9BF4DA81022B}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {3E8720B3-DBDD-498C-B383-2CC32A054E8F}
Expand Down
2 changes: 1 addition & 1 deletion eng/Versions.props
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@
<!-- 3rd party dependencies -->
<AzureIdentityVersion>1.10.3</AzureIdentityVersion>
<AngleSharpVersion>0.9.9</AngleSharpVersion>
<BenchmarkDotNetVersion>0.13.0</BenchmarkDotNetVersion>
<BenchmarkDotNetVersion>0.13.12</BenchmarkDotNetVersion>
<CastleCoreVersion>4.2.1</CastleCoreVersion>
<CommandLineParserVersion>2.3.0</CommandLineParserVersion>
<FSharpCoreVersion>6.0.0</FSharpCoreVersion>
Expand Down
3 changes: 2 additions & 1 deletion src/OpenApi/OpenApi.slnf
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
"src\\Http\\Routing\\src\\Microsoft.AspNetCore.Routing.csproj",
"src\\OpenApi\\src\\Microsoft.AspNetCore.OpenApi.csproj",
"src\\OpenApi\\test\\Microsoft.AspNetCore.OpenApi.Tests.csproj",
"src\\OpenApi\\sample\\Sample.csproj"
"src\\OpenApi\\sample\\Sample.csproj",
"src\\OpenApi\\perf\\Microsoft.AspNetCore.OpenApi.Microbenchmarks.csproj"
]
}
}
4 changes: 4 additions & 0 deletions src/OpenApi/perf/AssemblyInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

[assembly: BenchmarkDotNet.Attributes.AspNetCoreBenchmark]
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
<OutputType>Exe</OutputType>
<PreserveCompilationContext>true</PreserveCompilationContext>
</PropertyGroup>

<ItemGroup>
<Reference Include="BenchmarkDotNet" />
<Reference Include="Microsoft.AspNetCore" />
<Reference Include="Microsoft.AspNetCore.OpenApi" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\test\Microsoft.AspNetCore.OpenApi.Tests.csproj" />
</ItemGroup>

<ItemGroup>
<Compile Include="$(SharedSourceRoot)BenchmarkRunner\*.cs" />
</ItemGroup>

</Project>
106 changes: 106 additions & 0 deletions src/OpenApi/perf/TransformersBenchmark.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Reflection.Metadata;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Diagnosers;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Routing;
using Microsoft.OpenApi.Models;

namespace Microsoft.AspNetCore.OpenApi.Microbenchmarks;

/// <summary>
/// The following benchmarks are used to assess the memory and performance
/// impact of different types of transformers. In particular, we want to
/// measure the impact of (a) context-object creation and caching and (b)
/// enumerator usage when processing operations in a given document.
/// </summary>
[MemoryDiagnoser]
[EventPipeProfiler(EventPipeProfile.GcVerbose)]
public class TransformersBenchmark : OpenApiDocumentServiceTestBase
{
[Params(10, 100, 1000)]
public int InvocationCount { get; set; }

private readonly IEndpointRouteBuilder _builder = CreateBuilder();
private readonly OpenApiOptions _options = new OpenApiOptions();
private OpenApiDocumentService _documentService;

[GlobalSetup(Target = nameof(OperationTransformerAsDelegate))]
public void OperationTransformerAsDelegate_Setup()
{
_builder.MapGet("/", () => { });
for (var i = 0; i <= 1000; i++)
{
_options.UseOperationTransformer((operation, context, token) =>
{
operation.Description = "New Description";
return Task.CompletedTask;
});
}
_documentService = CreateDocumentService(_builder, _options);
}

[GlobalSetup(Target = nameof(ActivatedDocumentTransformer))]
public void ActivatedDocumentTransformer_Setup()
{
_builder.MapGet("/", () => { });
for (var i = 0; i <= 1000; i++)
{
_options.UseTransformer<ActivatedTransformer>();
}
_documentService = CreateDocumentService(_builder, _options);
}

[GlobalSetup(Target = nameof(DocumentTransformerAsDelegate))]
public void DocumentTransformerAsDelegate_Delegate()
{
_builder.MapGet("/", () => { });
for (var i = 0; i <= 1000; i++)
{
_options.UseTransformer((document, context, token) =>
{
document.Info.Description = "New Description";
return Task.CompletedTask;
});
}
_documentService = CreateDocumentService(_builder, _options);
}

[Benchmark]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What were the results? Are the comparable?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Example results are below. The OperationTransformerAsDelegate is more allocate-y than the others because of the use of the enumerator over the OpenApiOperations dictionary. We could optimize this but it makes the code a little less easy to read so I avoided this for now.

Method InvocationCount Mean Error StdDev Op/s Gen0 Gen1 Gen2 Allocated
OperationTransformerAsDelegate 10 502.24 us 2.784 us 2.604 us 1,991.07 3.9063 0.9766 0.9766 436.21 KB
ActivatedDocumentTransformer 10 50.65 us 0.510 us 0.477 us 19,744.86 0.3052 0.1221 0.0610 44.72 KB
DocumentTransformerAsDelegate 10 112.61 us 0.952 us 0.891 us 8,879.85 0.3662 0.2441 0.1221 44.72 KB
OperationTransformerAsDelegate 100 5,154.06 us 99.184 us 92.777 us 194.02 31.2500 - - 4282.05 KB
ActivatedDocumentTransformer 100 485.27 us 3.190 us 2.984 us 2,060.69 2.9297 0.9766 - 367.19 KB
DocumentTransformerAsDelegate 100 1,118.66 us 4.202 us 3.725 us 893.93 1.9531 - - 367.19 KB
OperationTransformerAsDelegate 1000 49,849.30 us 358.614 us 299.459 us 20.06 272.7273 - - 42820.56 KB
ActivatedDocumentTransformer 1000 4,973.16 us 61.507 us 57.534 us 201.08 23.4375 7.8125 - 3671.91 KB
DocumentTransformerAsDelegate 1000 11,212.38 us 81.451 us 76.189 us 89.19 15.6250 - - 3671.91 KB

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't we expect that one to be widely used? I thought the whole point of exposing the helper was so that app developers wouldn't have to roll their own. I think it might be worth a reduction in readability in this case.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I included the optimization in 40a9912. Description of it is here.

Original (with Dictionary enumerator)

Method TransformerCount Mean Error StdDev Op/s Gen0 Gen1 Allocated
OperationTransformerAsDelegate 10 2.156 us 0.0176 us 0.0147 us 463,813.7 0.0343 0.0076 4.15 KB
ActivatedDocumentTransformer 10 1.686 us 0.0216 us 0.0202 us 592,946.5 0.0324 0.0076 3.93 KB
DocumentTransformerAsDelegate 10 1.661 us 0.0177 us 0.0157 us 601,973.3 0.0305 0.0076 3.67 KB
OperationTransformerAsDelegate 100 7.310 us 0.0464 us 0.0387 us 136,796.5 0.0610 0.0153 7.66 KB
ActivatedDocumentTransformer 100 3.801 us 0.0311 us 0.0276 us 263,095.2 0.0496 0.0114 6.04 KB
DocumentTransformerAsDelegate 100 2.838 us 0.0337 us 0.0315 us 352,392.1 0.0305 0.0076 3.67 KB
OperationTransformerAsDelegate 1000 53.321 us 0.1793 us 0.1590 us 18,754.3 0.3052 0.0610 42.82 KB
ActivatedDocumentTransformer 1000 32.117 us 0.6423 us 0.6872 us 31,136.6 0.1831 - 28.13 KB
DocumentTransformerAsDelegate 1000 12.615 us 0.0257 us 0.0201 us 79,269.2 0.0153 - 3.67 KB

Improved (with OperationType-lookup)

Method TransformerCount Mean Error StdDev Op/s Gen0 Gen1 Allocated
OperationTransformerAsDelegate 10 2.561 us 0.0293 us 0.0274 us 390,501.5 0.0305 0.0076 3.7 KB
ActivatedDocumentTransformer 10 1.686 us 0.0108 us 0.0096 us 593,113.3 0.0324 0.0076 3.93 KB
DocumentTransformerAsDelegate 10 1.794 us 0.0134 us 0.0119 us 557,380.3 0.0305 0.0076 3.67 KB
OperationTransformerAsDelegate 100 8.255 us 0.1338 us 0.1252 us 121,144.2 0.0153 - 3.7 KB
ActivatedDocumentTransformer 100 4.016 us 0.0770 us 0.0824 us 248,976.9 0.0458 0.0076 6.04 KB
DocumentTransformerAsDelegate 100 2.762 us 0.0455 us 0.0426 us 362,068.0 0.0267 0.0076 3.67 KB
OperationTransformerAsDelegate 1000 60.630 us 0.1782 us 0.1667 us 16,493.6 - - 3.7 KB
ActivatedDocumentTransformer 1000 35.310 us 0.5062 us 0.4735 us 28,320.9 0.1831 - 27.13 KB
DocumentTransformerAsDelegate 1000 12.969 us 0.0904 us 0.0755 us 77,106.4 0.0153 - 3.67 KB

public async Task OperationTransformerAsDelegate()
{
for (var i = 0; i < InvocationCount; i++)
{
await _documentService.GetOpenApiDocumentAsync();
}
}

[Benchmark]
public async Task ActivatedDocumentTransformer()
{
for (var i = 0; i < InvocationCount; i++)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an odd pattern, why are you doing it? The results for different invocation counts should just be the same relative to each other.

If you think an individual operation is too fast you can have a hardcoded invocation count and use [Benchmark(OperationsPerInvoke = 1000)]

[Benchmark(OperationsPerInvoke = RequestParsingData.InnerLoopCount)]

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if one's quadratic? 😝

{
await _documentService.GetOpenApiDocumentAsync();
}
}

[Benchmark]
public async Task DocumentTransformerAsDelegate()
{
for (var i = 0; i < InvocationCount; i++)
{
await _documentService.GetOpenApiDocumentAsync();
}
}

private class ActivatedTransformer : IOpenApiDocumentTransformer
{
public Task TransformAsync(OpenApiDocument document, OpenApiDocumentTransformerContext context, CancellationToken cancellationToken)
{
document.Info.Description = "Info Description";
return Task.CompletedTask;
}
}
}
18 changes: 16 additions & 2 deletions src/OpenApi/sample/Program.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,24 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using Microsoft.OpenApi.Models;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddOpenApi("v1");
builder.Services.AddOpenApi("v2");
builder.Services.AddAuthentication().AddJwtBearer();

builder.Services.AddOpenApi("v1", options =>
{
options.AddHeader("X-Version", "1.0");
options.UseTransformer<BearerSecuritySchemeTransformer>();
});
builder.Services.AddOpenApi("v2", options => {
options.UseTransformer(new AddContactTransformer());
options.UseTransformer((document, context, token) => {
document.Info.License = new OpenApiLicense { Name = "MIT" };
return Task.CompletedTask;
});
});

var app = builder.Build();

Expand Down
1 change: 1 addition & 0 deletions src/OpenApi/sample/Sample.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

<ItemGroup>
<Reference Include="Microsoft.AspNetCore" />
<Reference Include="Microsoft.AspNetCore.Authentication.JwtBearer" />
<Reference Include="Microsoft.AspNetCore.Hosting" />
<Reference Include="Microsoft.AspNetCore.OpenApi" />
<Reference Include="Microsoft.AspNetCore.Http" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.OpenApi;
using Microsoft.OpenApi.Models;

public sealed class BearerSecuritySchemeTransformer(IAuthenticationSchemeProvider authenticationSchemeProvider) : IOpenApiDocumentTransformer
{
public async Task TransformAsync(OpenApiDocument document, OpenApiDocumentTransformerContext context, CancellationToken cancellationToken)
{
var authenticationSchemes = (authenticationSchemeProvider is not null)
? await authenticationSchemeProvider.GetAllSchemesAsync()
: [];
var requirements = authenticationSchemes
.Where(authScheme => authScheme.Name == "Bearer")
.ToDictionary(
(authScheme) => authScheme.Name,
(authScheme) => new OpenApiSecurityScheme
{
Type = SecuritySchemeType.Http,
Scheme = "bearer", // "bearer" refers to the header name here
In = ParameterLocation.Header,
BearerFormat = "Json Web Token"
});
document.Components ??= new OpenApiComponents();
document.Components.SecuritySchemes = requirements;
}
}
18 changes: 18 additions & 0 deletions src/OpenApi/sample/Transformers/AddContactTransformer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using Microsoft.AspNetCore.OpenApi;
using Microsoft.OpenApi.Models;

public sealed class AddContactTransformer : IOpenApiDocumentTransformer
{
public Task TransformAsync(OpenApiDocument document, OpenApiDocumentTransformerContext context, CancellationToken cancellationToken)
{
document.Info.Contact = new OpenApiContact
{
Name = "OpenAPI Enthusiast",
Email = "[email protected]"
};
return Task.CompletedTask;
}
}
26 changes: 26 additions & 0 deletions src/OpenApi/sample/Transformers/OperationTransformers.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using Microsoft.AspNetCore.OpenApi;
using Microsoft.OpenApi.Models;
using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.Extensions;

public static class OperationTransformers
{
public static OpenApiOptions AddHeader(this OpenApiOptions options, string headerName, string defaultValue)
{
return options.UseOperationTransformer((operation, context, cancellationToken) =>
{
var schema = OpenApiTypeMapper.MapTypeToOpenApiPrimitiveType(typeof(string));
schema.Default = new OpenApiString(defaultValue);
operation.Parameters.Add(new OpenApiParameter
{
Name = headerName,
In = ParameterLocation.Header,
Schema = schema
});
return Task.CompletedTask;
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public static IEndpointConventionBuilder MapOpenApi(this IEndpointRouteBuilder e
}
else
{
var document = await documentService.GetOpenApiDocumentAsync();
var document = await documentService.GetOpenApiDocumentAsync(context.RequestAborted);
var documentOptions = options.Get(documentName);
using var output = MemoryBufferWriter.Get();
using var writer = Utf8BufferTextWriter.Get(output);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not part of this PR, but on line 53 you call output.ToArray() which seems wasteful, was BodyWriter.CopyFromAsync(output) evaluated?

Expand Down
1 change: 1 addition & 0 deletions src/OpenApi/src/Microsoft.AspNetCore.OpenApi.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@

<ItemGroup>
<InternalsVisibleTo Include="Microsoft.AspNetCore.OpenApi.Tests" />
<InternalsVisibleTo Include="Microsoft.AspNetCore.OpenApi.Microbenchmarks" />
</ItemGroup>

<ItemGroup>
Expand Down
22 changes: 22 additions & 0 deletions src/OpenApi/src/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
@@ -1,15 +1,37 @@
#nullable enable
Microsoft.AspNetCore.Builder.OpenApiEndpointRouteBuilderExtensions
Microsoft.AspNetCore.OpenApi.IOpenApiDocumentTransformer.TransformAsync(Microsoft.OpenApi.Models.OpenApiDocument! document, Microsoft.AspNetCore.OpenApi.OpenApiDocumentTransformerContext! context, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task!
Microsoft.AspNetCore.OpenApi.OpenApiOperationTransformerContext.Description.get -> Microsoft.AspNetCore.Mvc.ApiExplorer.ApiDescription!
Microsoft.AspNetCore.OpenApi.OpenApiOperationTransformerContext.Description.init -> void
Microsoft.AspNetCore.OpenApi.OpenApiOptions
Microsoft.AspNetCore.OpenApi.OpenApiOptions.DocumentName.get -> string!
Microsoft.AspNetCore.OpenApi.OpenApiOptions.OpenApiOptions() -> void
Microsoft.AspNetCore.OpenApi.OpenApiOptions.OpenApiVersion.get -> Microsoft.OpenApi.OpenApiSpecVersion
Microsoft.AspNetCore.OpenApi.OpenApiOptions.OpenApiVersion.set -> void
Microsoft.AspNetCore.OpenApi.OpenApiOptions.ShouldInclude.get -> System.Func<Microsoft.AspNetCore.Mvc.ApiExplorer.ApiDescription!, bool>!
Microsoft.AspNetCore.OpenApi.OpenApiOptions.ShouldInclude.set -> void
Microsoft.AspNetCore.OpenApi.OpenApiOptions.UseOperationTransformer(System.Func<Microsoft.OpenApi.Models.OpenApiOperation!, Microsoft.AspNetCore.OpenApi.OpenApiOperationTransformerContext!, System.Threading.CancellationToken, System.Threading.Tasks.Task!>! transformer) -> Microsoft.AspNetCore.OpenApi.OpenApiOptions!
Microsoft.AspNetCore.OpenApi.OpenApiOptions.UseTransformer(Microsoft.AspNetCore.OpenApi.IOpenApiDocumentTransformer! transformer) -> Microsoft.AspNetCore.OpenApi.OpenApiOptions!
Microsoft.AspNetCore.OpenApi.OpenApiOptions.UseTransformer(System.Func<Microsoft.OpenApi.Models.OpenApiDocument!, Microsoft.AspNetCore.OpenApi.OpenApiDocumentTransformerContext!, System.Threading.CancellationToken, System.Threading.Tasks.Task!>! transformer) -> Microsoft.AspNetCore.OpenApi.OpenApiOptions!
Microsoft.AspNetCore.OpenApi.OpenApiOptions.UseTransformer<TTransformerType>() -> Microsoft.AspNetCore.OpenApi.OpenApiOptions!
Microsoft.Extensions.DependencyInjection.OpenApiServiceCollectionExtensions
static Microsoft.AspNetCore.Builder.OpenApiEndpointRouteBuilderExtensions.MapOpenApi(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder! endpoints, string! pattern = "/openapi/{documentName}.json") -> Microsoft.AspNetCore.Builder.IEndpointConventionBuilder!
static Microsoft.Extensions.DependencyInjection.OpenApiServiceCollectionExtensions.AddOpenApi(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services) -> Microsoft.Extensions.DependencyInjection.IServiceCollection!
static Microsoft.Extensions.DependencyInjection.OpenApiServiceCollectionExtensions.AddOpenApi(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services, string! documentName) -> Microsoft.Extensions.DependencyInjection.IServiceCollection!
static Microsoft.Extensions.DependencyInjection.OpenApiServiceCollectionExtensions.AddOpenApi(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services, string! documentName, System.Action<Microsoft.AspNetCore.OpenApi.OpenApiOptions!>! configureOptions) -> Microsoft.Extensions.DependencyInjection.IServiceCollection!
static Microsoft.Extensions.DependencyInjection.OpenApiServiceCollectionExtensions.AddOpenApi(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services, System.Action<Microsoft.AspNetCore.OpenApi.OpenApiOptions!>! configureOptions) -> Microsoft.Extensions.DependencyInjection.IServiceCollection!
Microsoft.AspNetCore.OpenApi.IOpenApiDocumentTransformer
Microsoft.AspNetCore.OpenApi.OpenApiDocumentTransformerContext
Microsoft.AspNetCore.OpenApi.OpenApiDocumentTransformerContext.ApplicationServices.get -> System.IServiceProvider!
Microsoft.AspNetCore.OpenApi.OpenApiDocumentTransformerContext.ApplicationServices.init -> void
Microsoft.AspNetCore.OpenApi.OpenApiDocumentTransformerContext.DescriptionGroups.get -> System.Collections.Generic.IReadOnlyList<Microsoft.AspNetCore.Mvc.ApiExplorer.ApiDescriptionGroup!>!
Microsoft.AspNetCore.OpenApi.OpenApiDocumentTransformerContext.DescriptionGroups.init -> void
Microsoft.AspNetCore.OpenApi.OpenApiDocumentTransformerContext.DocumentName.get -> string!
Microsoft.AspNetCore.OpenApi.OpenApiDocumentTransformerContext.DocumentName.init -> void
Microsoft.AspNetCore.OpenApi.OpenApiDocumentTransformerContext.OpenApiDocumentTransformerContext() -> void
Microsoft.AspNetCore.OpenApi.OpenApiOperationTransformerContext
Microsoft.AspNetCore.OpenApi.OpenApiOperationTransformerContext.ApplicationServices.get -> System.IServiceProvider!
Microsoft.AspNetCore.OpenApi.OpenApiOperationTransformerContext.ApplicationServices.init -> void
Microsoft.AspNetCore.OpenApi.OpenApiOperationTransformerContext.DocumentName.get -> string!
Microsoft.AspNetCore.OpenApi.OpenApiOperationTransformerContext.DocumentName.init -> void
Microsoft.AspNetCore.OpenApi.OpenApiOperationTransformerContext.OpenApiOperationTransformerContext() -> void
1 change: 1 addition & 0 deletions src/OpenApi/src/Services/OpenApiConstants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ internal static class OpenApiConstants
internal const string DefaultDocumentName = "v1";
internal const string DefaultOpenApiVersion = "1.0.0";
internal const string DefaultOpenApiRoute = "/openapi/{documentName}.json";
internal const string DescriptionId = "x-aspnetcore-id";
}
Loading