| File: Builder\EndpointFilterExtensions.cs | Web Access |
| Project: src\aspnetcore\src\Http\Routing\src\Microsoft.AspNetCore.Routing.csproj (Microsoft.AspNetCore.Routing) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics.CodeAnalysis; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Routing; using Microsoft.Extensions.DependencyInjection; namespace Microsoft.AspNetCore.Http; /// <summary> /// Extension methods for adding <see cref="IEndpointFilter"/> to a route handler. /// </summary> public static class EndpointFilterExtensions { /// <summary> /// Registers a filter onto the route handler. /// </summary> /// <param name="builder">The <see cref="RouteHandlerBuilder"/>.</param> /// <param name="filter">The <see cref="IEndpointFilter"/> to register.</param> /// <returns>A <see cref="RouteHandlerBuilder"/> that can be used to further customize the route handler.</returns> public static TBuilder AddEndpointFilter<TBuilder>(this TBuilder builder, IEndpointFilter filter) where TBuilder : IEndpointConventionBuilder => builder.AddEndpointFilterFactory((routeHandlerContext, next) => (context) => filter.InvokeAsync(context, next)); /// <summary> /// Registers a filter of type <typeparamref name="TFilterType"/> onto the route handler. /// </summary> /// <typeparam name="TBuilder">The type of the <see cref="IEndpointConventionBuilder"/> to configure.</typeparam> /// <typeparam name="TFilterType">The type of the <see cref="IEndpointFilter"/> to register.</typeparam> /// <param name="builder">The <see cref="RouteHandlerBuilder"/>.</param> /// <returns>A <see cref="RouteHandlerBuilder"/> that can be used to further customize the route handler.</returns> public static TBuilder AddEndpointFilter<TBuilder, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TFilterType>(this TBuilder builder) where TBuilder : IEndpointConventionBuilder where TFilterType : IEndpointFilter { // We call `CreateFactory` twice here since the `CreateFactory` API does not support optional arguments. // See https://github.com/dotnet/runtime/issues/67309 for more info. ObjectFactory filterFactory; try { filterFactory = ActivatorUtilities.CreateFactory(typeof(TFilterType), new[] { typeof(EndpointFilterFactoryContext) }); } catch (InvalidOperationException) { filterFactory = ActivatorUtilities.CreateFactory(typeof(TFilterType), Type.EmptyTypes); } builder.AddEndpointFilterFactory((routeHandlerContext, next) => { var invokeArguments = new[] { routeHandlerContext }; return (context) => { var filter = (IEndpointFilter)filterFactory.Invoke(context.HttpContext.RequestServices, invokeArguments); return filter.InvokeAsync(context, next); }; }); return builder; } /// <summary> /// Registers a filter of type <typeparamref name="TFilterType"/> onto the route handler. /// </summary> /// <typeparam name="TFilterType">The type of the <see cref="IEndpointFilter"/> to register.</typeparam> /// <param name="builder">The <see cref="RouteHandlerBuilder"/>.</param> /// <returns>A <see cref="RouteHandlerBuilder"/> that can be used to further customize the route handler.</returns> public static RouteHandlerBuilder AddEndpointFilter<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TFilterType>(this RouteHandlerBuilder builder) where TFilterType : IEndpointFilter { // We have a RouteHandlerBuiler and GroupRouteBuilder-specific AddFilter methods for convenience so you don't have to specify both arguments most the time. return builder.AddEndpointFilter<RouteHandlerBuilder, TFilterType>(); } /// <summary> /// Registers a filter of type <typeparamref name="TFilterType"/> onto the route handler. /// </summary> /// <typeparam name="TFilterType">The type of the <see cref="IEndpointFilter"/> to register.</typeparam> /// <param name="builder">The <see cref="RouteHandlerBuilder"/>.</param> /// <returns>A <see cref="RouteHandlerBuilder"/> that can be used to further customize the route handler.</returns> public static RouteGroupBuilder AddEndpointFilter<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TFilterType>(this RouteGroupBuilder builder) where TFilterType : IEndpointFilter { // We have a RouteHandlerBuiler and GroupRouteBuilder-specific AddFilter methods for convenience so you don't have to specify both arguments most the time. return builder.AddEndpointFilter<RouteGroupBuilder, TFilterType>(); } /// <summary> /// Registers a filter given a delegate onto the route handler. /// </summary> /// <param name="builder">The <see cref="RouteHandlerBuilder"/>.</param> /// <param name="routeHandlerFilter">A method representing the core logic of the filter.</param> /// <returns>A <see cref="RouteHandlerBuilder"/> that can be used to further customize the route handler.</returns> public static TBuilder AddEndpointFilter<TBuilder>(this TBuilder builder, Func<EndpointFilterInvocationContext, EndpointFilterDelegate, ValueTask<object?>> routeHandlerFilter) where TBuilder : IEndpointConventionBuilder { return builder.AddEndpointFilterFactory((routeHandlerContext, next) => (context) => routeHandlerFilter(context, next)); } /// <summary> /// Register a filter given a delegate representing the filter factory. /// </summary> /// <param name="builder">The <see cref="RouteHandlerBuilder"/>.</param> /// <param name="filterFactory">A method representing the logic for constructing the filter.</param> /// <returns>A <see cref="RouteHandlerBuilder"/> that can be used to further customize the route handler.</returns> public static TBuilder AddEndpointFilterFactory<TBuilder>(this TBuilder builder, Func<EndpointFilterFactoryContext, EndpointFilterDelegate, EndpointFilterDelegate> filterFactory) where TBuilder : IEndpointConventionBuilder { builder.Add(endpointBuilder => { endpointBuilder.FilterFactories.Add(filterFactory); }); return builder; } }