Background and Motivation
With #43000, we've approved adding RequestDelegateFactoryOptions.EndpointBuilder and EndpointFilterFactoryContext.EndpointBuilder so filters can get full access to more metadata like the RoutePattern (with a downcast) and DisplayName.
I think IEndpointMetadataProvider and IEndpointParameterMetadataProvider deserve the same treatment.
Also see #42827 (comment) for more context.
Proposed API
namespace Microsoft.AspNetCore.Http.Metadata;
public interface IEndpointMetadataProvider
{
- static abstract void PopulateMetadata(EndpointMetadataContext context);
+ static abstract void PopulateMetadata(MethodInfo method, EndpointBuilder builder);
}
public interface IEndpointParameterMetadataProvider
{
- static abstract void PopulateMetadata(EndpointParameterMetadataContext parameterContext);
+ static abstract void PopulateMetadata(ParameterInfo parameter, EndpointBuilder builder);
}
- public sealed class EndpointMetadataContext
- {
- public EndpointMetadataContext(MethodInfo method, IList<object> endpointMetadata, IServiceProvider applicationServices);
- public MethodInfo Method { get; }
- public IList<object> EndpointMetadata { get; }
- public IServiceProvider ApplicationServices { get; }
- }
- public sealed class EndpointParameterMetadataContext
- {
- public EndpointParameterMetadataContext(ParameterInfo parameter, IList<object> endpointMetadata, IServiceProvider applicationServices);
- public ParameterInfo Parameter { get; }
- public IList<object> EndpointMetadata { get; }
- public IServiceProvider ApplicationServices { get; }
- }
Usage Examples
static void IEndpointMetadataProvider.PopulateMetadata(MethodInfo method, EndpointBuilder builder)
{
builder.Metadata.Add(new ProducesResponseTypeMetadata(typeof(TValue), StatusCodes.Status200OK, "application/json"));
}
Alternative Designs
We could change context. to reference a builder in case we want to add more parameters in the future that are not on the EndpointBuilder in some way. I find this is clunky though, and I'm not sure how likely additional future parameters really are.
namespace Microsoft.AspNetCore.Http.Metadata;
public sealed class EndpointMetadataContext
{
- public EndpointMetadataContext(MethodInfo method, IList<object> endpointMetadata, IServiceProvider applicationServices);
+ public EndpointMetadataContext(MethodInfo method, EndpointBuilder builder);
public MethodInfo Method { get; }
- public IList<object> EndpointMetadata { get; }
- public IServiceProvider ApplicationServices { get; }
+ public EndpointBuilder EndpointBuilder { get; }
}
public sealed class EndpointParameterMetadataContext
{
- public EndpointParameterMetadataContext(ParameterInfo parameter, IList<object> endpointMetadata, IServiceProvider applicationServices);
- public EndpointParameterMetadataContext(ParameterInfo prameter, EndpointBuilder builder);
public ParameterInfo Parameter { get; }
- public IList<object> EndpointMetadata { get; }
- public IServiceProvider ApplicationServices { get; }
+ public EndpointBuilder EndpointBuilder { get; }
}
Risks
With the primary proposal, we lose out on having a context, so it's harder to add parameters in the future if we find it will be necesarry.
Third-party IEndpointMetadataProvider implementations need to rewrite their PopulateMetadata methods with either change, but it should be pretty mechanical.
@DamianEdwards
Background and Motivation
With #43000, we've approved adding
RequestDelegateFactoryOptions.EndpointBuilderandEndpointFilterFactoryContext.EndpointBuilderso filters can get full access to more metadata like theRoutePattern(with a downcast) andDisplayName.I think
IEndpointMetadataProviderandIEndpointParameterMetadataProviderdeserve the same treatment.Also see #42827 (comment) for more context.
Proposed API
namespace Microsoft.AspNetCore.Http.Metadata; public interface IEndpointMetadataProvider { - static abstract void PopulateMetadata(EndpointMetadataContext context); + static abstract void PopulateMetadata(MethodInfo method, EndpointBuilder builder); } public interface IEndpointParameterMetadataProvider { - static abstract void PopulateMetadata(EndpointParameterMetadataContext parameterContext); + static abstract void PopulateMetadata(ParameterInfo parameter, EndpointBuilder builder); } - public sealed class EndpointMetadataContext - { - public EndpointMetadataContext(MethodInfo method, IList<object> endpointMetadata, IServiceProvider applicationServices); - public MethodInfo Method { get; } - public IList<object> EndpointMetadata { get; } - public IServiceProvider ApplicationServices { get; } - } - public sealed class EndpointParameterMetadataContext - { - public EndpointParameterMetadataContext(ParameterInfo parameter, IList<object> endpointMetadata, IServiceProvider applicationServices); - public ParameterInfo Parameter { get; } - public IList<object> EndpointMetadata { get; } - public IServiceProvider ApplicationServices { get; } - }Usage Examples
Alternative Designs
We could change context. to reference a builder in case we want to add more parameters in the future that are not on the
EndpointBuilderin some way. I find this is clunky though, and I'm not sure how likely additional future parameters really are.namespace Microsoft.AspNetCore.Http.Metadata; public sealed class EndpointMetadataContext { - public EndpointMetadataContext(MethodInfo method, IList<object> endpointMetadata, IServiceProvider applicationServices); + public EndpointMetadataContext(MethodInfo method, EndpointBuilder builder); public MethodInfo Method { get; } - public IList<object> EndpointMetadata { get; } - public IServiceProvider ApplicationServices { get; } + public EndpointBuilder EndpointBuilder { get; } } public sealed class EndpointParameterMetadataContext { - public EndpointParameterMetadataContext(ParameterInfo parameter, IList<object> endpointMetadata, IServiceProvider applicationServices); - public EndpointParameterMetadataContext(ParameterInfo prameter, EndpointBuilder builder); public ParameterInfo Parameter { get; } - public IList<object> EndpointMetadata { get; } - public IServiceProvider ApplicationServices { get; } + public EndpointBuilder EndpointBuilder { get; } }Risks
With the primary proposal, we lose out on having a context, so it's harder to add parameters in the future if we find it will be necesarry.
Third-party
IEndpointMetadataProviderimplementations need to rewrite theirPopulateMetadatamethods with either change, but it should be pretty mechanical.@DamianEdwards