You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
See #66408. This proposal serves as an alternative.
In short, today, OpenAPI requires document names to be known at the time when the services are registered. There can be scenarios (e.g, Asp.Versioning) when the document names are not known that early.
Proposed API
Add IAdditionalOpenApiDocumentNameProvider:
+ namespace Microsoft.AspNetCore.OpenApi.Extensions;++ /// <summary>+ /// An interface that lets users provide additional OpenAPI document names.+ /// </summary>+ public interface IAdditionalOpenApiDocumentNameProvider+ {+ /// <summary>+ /// Gets the additional document names.+ /// </summary>+ public IEnumerable<string> DocumentNames { get; }+ }
Make documentName in AddOpenApi nullable.
namespace Microsoft.Extensions.DependencyInjection;
public static class OpenApiServiceCollectionExtensions
{
- public static IServiceCollection AddOpenApi(this IServiceCollection services, string documentName)+ public static IServiceCollection AddOpenApi(this IServiceCollection services, string? documentName)
}
Exact changes:
All keyed OpenAPI services will be registered using KeyedService.AnyKey. This allows document names that are not known during the time of building services to still work as expected.
If AddOpenApi is called with null document name, we won't register NamedService<OpenApiDocumentService> (the whole purpose of this service is to get the registered document names later - at this point, we don't even have any document name)
If AddOpenApi is called with a non-null document name, we register NamedService<OpenApiDocumentService>.
The only AddOpenApi overload that can accept a null documentName is the simple overload that doesn't configure OpenApiOptions. The OpenApiOptions is per-document and cannot work with a null document name. In future, if we ever needed to have some "global" options that applies to all documents in this mode, that can probably be its own simplified options class.
Whenever we want to know the valid document names, we combine that information from two sources:
The new interface, if registered.
The internal NamedService<OpenApiDocumentService> which is used when AddOpenApi is given a non-null document name.
Because our current OpenApiOptions is per-document, the above cannot work for AddOpenApi(documentName: null).
The source generated code can then be updated to throw NotSupportedException for null document names.
Alternative Designs
We should consider if we should take this a step further. As currently proposed and implemented in prototype, the public IAdditionalOpenApiDocumentNameProvider only really provides the additional document names, as the name suggests.
We still have an internal IDocumentProvider interface. One of its responsibilities is to provide the document names, and its implementation is updated to "combine" all the document names (ones added explicitly through AddOpenApi and the additional ones provided externally via the new interface)
What we can consider is, if the public interface should simply be responsible of providing all the document names. This might also help us clean all the reflection logic for build-time generation. If we want to do so, we need to have a concrete API shape for this.
Background and Motivation
See #66408. This proposal serves as an alternative.
In short, today, OpenAPI requires document names to be known at the time when the services are registered. There can be scenarios (e.g, Asp.Versioning) when the document names are not known that early.
Proposed API
Add
IAdditionalOpenApiDocumentNameProvider:Make documentName in AddOpenApi nullable.
namespace Microsoft.Extensions.DependencyInjection; public static class OpenApiServiceCollectionExtensions { - public static IServiceCollection AddOpenApi(this IServiceCollection services, string documentName) + public static IServiceCollection AddOpenApi(this IServiceCollection services, string? documentName) }Exact changes:
KeyedService.AnyKey. This allows document names that are not known during the time of building services to still work as expected.AddOpenApiis called with null document name, we won't registerNamedService<OpenApiDocumentService>(the whole purpose of this service is to get the registered document names later - at this point, we don't even have any document name)AddOpenApiis called with a non-null document name, we registerNamedService<OpenApiDocumentService>.NamedService<OpenApiDocumentService>which is used when AddOpenApi is given a non-null document name.Usage Examples
See current prototype in dotnet/aspnet-api-versioning#1186 (dotnet/aspnet-api-versioning@5005039). In short:
Then
OpenApiVersionedDocumentNamesProvideris responsible for providing the additional document names.Important
Our XmlCommentGenerator intercepts the
AddOpenApicall that doesn't accept options and forwards it to something like the following:Because our current OpenApiOptions is per-document, the above cannot work for
AddOpenApi(documentName: null).The source generated code can then be updated to throw
NotSupportedExceptionfor null document names.Alternative Designs
We should consider if we should take this a step further. As currently proposed and implemented in prototype, the public
IAdditionalOpenApiDocumentNameProvideronly really provides the additional document names, as the name suggests.We still have an internal
IDocumentProviderinterface. One of its responsibilities is to provide the document names, and its implementation is updated to "combine" all the document names (ones added explicitly through AddOpenApi and the additional ones provided externally via the new interface)What we can consider is, if the public interface should simply be responsible of providing all the document names. This might also help us clean all the reflection logic for build-time generation. If we want to do so, we need to have a concrete API shape for this.
Risks