-
Notifications
You must be signed in to change notification settings - Fork 10.5k
Description
Background and Motivation
In the past, there have been requests to support adding endpoint filters at the global level (see #43237). More recently, the need for global filters has emerged as part of the work to support a source generator-based validation implementation in minimal APIs (see #46349).
Endpoint filters are implemented on top of ASP.NET Core's conventions API and the IEndpointConventionBuilder. To support global filters, we'll need to expose an API for accessing an underlying IEndpointConventionBuilder on the top-level WebApplication.
Proposed API
// Assembly: Microsoft.AspNetCore
namespace Microsoft.AspNetCore.Builder;
public sealed class WebApplication : IHost, IApplicationBuilder, IEndpointRouteBuilder, IAsyncDisposable
{
+ public IEndpointConventionBuilder Conventions { get; }
}Usage Examples
var app = WebApplication.Create();
// Register parameter validations for minimal APIs globally
app.Conventions.WithValidation();
// Disable anti-forgery checks on form-based endpoints during development
if (app.Environment.IsDevelopment())
{
app.Conventions.DisableAntiforgery();
}
// Require authorization on all endpoints in the application
app.Conventions.RequireAuthorization();
app.MapGet("/", () => "Hello world!");
app.Run();Alternative Designs
Instead of exposing the IEndpointConventionBuilder as a property on the WebApplication class, we can consider implementing the IEndpointConventionBuilder interface directly on the class.
// Assembly: Microsoft.AspNetCore
namespace Microsoft.AspNetCore.Builder;
public sealed class WebApplication : IHost, IApplicationBuilder, IEndpointRouteBuilder, IAsyncDisposable, IEndpointConventionBuilder
{
+ public void Add(Action<EndpointBuilder> convention) { }
+ public void Finally(Action<EndpointBuilder> finallyConvention) { }
}However, there's hesitation around having WebApplication implement the IEndpointConventionBuilder which is an interface with multiple extension methods (ref) that might pollute the API surface for the WebApplication. Isolating these extension methods to a property keeps the Intellisense on WebApplication clean. On the other hand, there are discoverability questions around the Conventions property.
Alternatively, we can consider exposing a deconstructor on the WebApplication class that allows the user to pull out the underlying IEndpointConventionBuillder.
// Assembly: Microsoft.AspNetCore
namespace Microsoft.AspNetCore.Builder;
public sealed class WebApplication : IHost, IApplicationBuilder, IEndpointRouteBuilder, IAsyncDisposable
{
+ public void Deconstruct(out IEndpointConventionBuilder conventions) { }
}Risks
- The name
Conventionscomes from an implementation details of the framework and is not as familiar to users as related terms like "filter" and "metadata", which map to conventions under the hood. This might impact the discoverability of this feature. - Supporting global filters on WebApplication means that users will need to understand the distinction between global middleware and global filters. We'll need to make sure that the distinction is clear to users who might not be familiar with the different pipelines.
- Since conventions are global and applied to all
RouteEndpointsthere is a chance that users can use the API in a way that results in non-sensical permutations. For example, a user can invokeapp.Conventions.WithGroupName("global")to add a global group name to all endpoints. This concept only makes sense in endpoints that use link-generation or OpenAPI and would be non-sensical of Blazor or SignalR endpoints.