-
Notifications
You must be signed in to change notification settings - Fork 9.8k
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
OpenAPI convention on route group cannot examine endpoint-specific metadata #42750
Comments
Two different ideas here:
|
Background and MotivationSee above. Proposed API 1Technically, this nothing that would show up in a // This is a diff if the Type we put in EndpointBuilder.Metadata
- Microsoft.OpenApi.Models.OpenApiOperation
+ System.Func<Microsoft.OpenApi.Models.OpenApiOperation> Usage Examplevar operation = endpoint.Metadata.GetMetadata<Func<OpenApiOperation>>()?.Invoke(); Alternative DesignsProposed API 2A problem with the above two proposals is that they may be considered too lazy. We don't want to generate the // This is a diff if the Type we put in EndpointBuilder.Metadata
// Use IEnumerable<object> instead of EndpointMetadataCollection to better support ActionDescriptor.EndopintMetadata
- Microsoft.OpenApi.Models.OpenApiOperation
+ System.Func<IEnumerable<object>, Microsoft.OpenApi.Models.OpenApiOperation> Proposed API 3Instead of using (or abusing) + namespace Microsoft.AspNetCore.OpenApi;
+
+ public interface IOpenApiMetadata
+ {
+ OpenApiOperation OpenApiOperation { get; }
+ } Proposed API 4A problem main proposal is that it may be considered too lazy. We don't want to generate the We could add a namespace Microsoft.AspNetCore.Routing;
public sealed class RouteEndpointBuilder : EndpointBuilder
{
+ public void Finally(Action finalizeBuild);
} RisksThe main risk of the primary and secondary proposal is needing to support a clunky API that we'd like to change in the future but cannot easily. The third easier to use (if you can swallow taking a The fourth proposal is probably the most convenient to use, but it does feel a bit heavy handed to add a new @captainsafia @BrennanConroy @davidfowl @brunolins16 @domaindrivendev @RicoSuter |
Thank you for submitting this for API review. This will be reviewed by @dotnet/aspnet-api-review at the next meeting of the ASP.NET Core API Review group. Please ensure you take a look at the API review process documentation and ensure that:
|
Finally might be useful for other things like building optimized caches for metadata, so maybe it's worth discussing that API and seeing what it would look like for this scenario. |
API Review Notes:
API Approved! namespace Microsoft.AspNetCore.Builder;
public interface IEndpointConventionBuilder
{
void Add(Action<EndpointBuilder> convention);
+ void Finally(Action<EndpointBuilder> finallyConvention);
}
namespace Microsoft.AspNetCore.Routing;
public sealed class RouteGroupContext
{
- public RouteGroupContext(RoutePattern prefix, IReadOnlyList<Action<EndpointBuilder>> conventions, IServiceProvider applicationServices);
- public RoutePattern Prefix { get; }
+ public required RoutePattern Prefix { get; init; }
- public IReadOnlyList<Action<EndpointBuilder>> Conventions { get; }
+ public IReadOnlyList<Action<EndpointBuilder>> Conventions { get; init; }
+ public IReadOnlyList<Action<EndpointBuilder>> FinallyConventions { get; init; }
- public IServiceProvider ApplicationServices { get; }
+ public IServiceProvider ApplicationServices { get; init; }
} |
What are your thoughts on renaming It feels weird to prefix this name with an adverb when an adjective makes more sense. |
I like that If we did go with Okay, I think you've convinced me. Here's the updated proposal: namespace Microsoft.AspNetCore.Builder;
public interface IEndpointConventionBuilder
{
void Add(Action<EndpointBuilder> convention);
+ void Finally(Action<EndpointBuilder> finallyConvention);
}
namespace Microsoft.AspNetCore.Routing;
public sealed class RouteGroupContext
{
- public RouteGroupContext(RoutePattern prefix, IReadOnlyList<Action<EndpointBuilder>> conventions, IServiceProvider applicationServices);
- public RoutePattern Prefix { get; }
+ public required RoutePattern Prefix { get; init; }
- public IReadOnlyList<Action<EndpointBuilder>> Conventions { get; }
+ public IReadOnlyList<Action<EndpointBuilder>> Conventions { get; init; }
+ public IReadOnlyList<Action<EndpointBuilder>> FinalConventions { get; init; }
- public IServiceProvider ApplicationServices { get; }
+ public IServiceProvider ApplicationServices { get; init; }
} Does that look good to you @captainsafia? Everyone else? |
Thank you for submitting this for API review. This will be reviewed by @dotnet/aspnet-api-review at the next meeting of the ASP.NET Core API Review group. Please ensure you take a look at the API review process documentation and ensure that:
|
Looks good with one adjustment for the parameter name on the - void Finally(Action<EndpointBuilder> finallyConvention);
+ void Finally(Action<EndpointBuilder> finalConvention);
This seems sensible to me regardless of whether it's |
One thing that I don't like about flipping the Also, I think @dotnet/aspnet-api-review Does anyone else have an opinion on |
@captainsafia and I discussed this more. While she's not a fan, in the interest of time, we're going with what was already approved in #42750 (comment). namespace Microsoft.AspNetCore.Builder;
public interface IEndpointConventionBuilder
{
void Add(Action<EndpointBuilder> convention);
+ void Finally(Action<EndpointBuilder> finallyConvention);
}
namespace Microsoft.AspNetCore.Routing;
public sealed class RouteGroupContext
{
- public RouteGroupContext(RoutePattern prefix, IReadOnlyList<Action<EndpointBuilder>> conventions, IServiceProvider applicationServices);
- public RoutePattern Prefix { get; }
+ public required RoutePattern Prefix { get; init; }
- public IReadOnlyList<Action<EndpointBuilder>> Conventions { get; }
+ public IReadOnlyList<Action<EndpointBuilder>> Conventions { get; init; }
+ public IReadOnlyList<Action<EndpointBuilder>> FinallyConventions { get; init; }
- public IServiceProvider ApplicationServices { get; }
+ public IServiceProvider ApplicationServices { get; init; }
} |
Is there an existing issue for this?
Describe the bug
The OpenAPI convention registered by the
WithOpenApi
extension examines metadata on an endpoint to produce an OpenAPI annotation.At the moment, group conventions have no way running after conventions on it's child endpoint and cannot examine their metadata. As a result, the following code will not produce the correct OpenAPI annotation because the
Produces
-metadata cannot be examined.Since there are challenges to supporting controlling ordering of conventions on the builder and this problem is unique to the OpenAPI convention, it might be sufficient to consider a one-off solutions for OpenAPI to resolve this.
Expected Behavior
Metadata registered on an individual endpoint should be observable by the OpenAPI convention on that endpoint's parent group.
The text was updated successfully, but these errors were encountered: