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
Conventions
comes 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
RouteEndpoints
there 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.