|
@@ -102,15 +102,15 @@ public static partial class RequestDelegateFactory
|
|
|
private static readonly BinaryExpression TempSourceStringNullExpr = Expression.Equal(TempSourceStringExpr, Expression.Constant(null));
|
|
private static readonly BinaryExpression TempSourceStringNullExpr = Expression.Equal(TempSourceStringExpr, Expression.Constant(null));
|
|
|
private static readonly UnaryExpression TempSourceStringIsNotNullOrEmptyExpr = Expression.Not(Expression.Call(StringIsNullOrEmptyMethod, TempSourceStringExpr));
|
|
private static readonly UnaryExpression TempSourceStringIsNotNullOrEmptyExpr = Expression.Not(Expression.Call(StringIsNullOrEmptyMethod, TempSourceStringExpr));
|
|
|
|
|
|
|
|
- private static readonly ConstructorInfo DefaultRouteHandlerInvocationContextConstructor = typeof(DefaultRouteHandlerInvocationContext).GetConstructor(new[] { typeof(HttpContext), typeof(object[]) })!;
|
|
|
|
|
- private static readonly MethodInfo RouteHandlerInvocationContextGetArgument = typeof(RouteHandlerInvocationContext).GetMethod(nameof(RouteHandlerInvocationContext.GetArgument))!;
|
|
|
|
|
|
|
+ private static readonly ConstructorInfo DefaultEndpointFilterInvocationContextConstructor = typeof(DefaultEndpointFilterInvocationContext).GetConstructor(new[] { typeof(HttpContext), typeof(object[]) })!;
|
|
|
|
|
+ private static readonly MethodInfo EndpointFilterInvocationContextGetArgument = typeof(EndpointFilterInvocationContext).GetMethod(nameof(EndpointFilterInvocationContext.GetArgument))!;
|
|
|
private static readonly PropertyInfo ListIndexer = typeof(IList<object>).GetProperty("Item")!;
|
|
private static readonly PropertyInfo ListIndexer = typeof(IList<object>).GetProperty("Item")!;
|
|
|
- private static readonly ParameterExpression FilterContextExpr = Expression.Parameter(typeof(RouteHandlerInvocationContext), "context");
|
|
|
|
|
- private static readonly MemberExpression FilterContextHttpContextExpr = Expression.Property(FilterContextExpr, typeof(RouteHandlerInvocationContext).GetProperty(nameof(RouteHandlerInvocationContext.HttpContext))!);
|
|
|
|
|
- private static readonly MemberExpression FilterContextArgumentsExpr = Expression.Property(FilterContextExpr, typeof(RouteHandlerInvocationContext).GetProperty(nameof(RouteHandlerInvocationContext.Arguments))!);
|
|
|
|
|
|
|
+ private static readonly ParameterExpression FilterContextExpr = Expression.Parameter(typeof(EndpointFilterInvocationContext), "context");
|
|
|
|
|
+ private static readonly MemberExpression FilterContextHttpContextExpr = Expression.Property(FilterContextExpr, typeof(EndpointFilterInvocationContext).GetProperty(nameof(EndpointFilterInvocationContext.HttpContext))!);
|
|
|
|
|
+ private static readonly MemberExpression FilterContextArgumentsExpr = Expression.Property(FilterContextExpr, typeof(EndpointFilterInvocationContext).GetProperty(nameof(EndpointFilterInvocationContext.Arguments))!);
|
|
|
private static readonly MemberExpression FilterContextHttpContextResponseExpr = Expression.Property(FilterContextHttpContextExpr, typeof(HttpContext).GetProperty(nameof(HttpContext.Response))!);
|
|
private static readonly MemberExpression FilterContextHttpContextResponseExpr = Expression.Property(FilterContextHttpContextExpr, typeof(HttpContext).GetProperty(nameof(HttpContext.Response))!);
|
|
|
private static readonly MemberExpression FilterContextHttpContextStatusCodeExpr = Expression.Property(FilterContextHttpContextResponseExpr, typeof(HttpResponse).GetProperty(nameof(HttpResponse.StatusCode))!);
|
|
private static readonly MemberExpression FilterContextHttpContextStatusCodeExpr = Expression.Property(FilterContextHttpContextResponseExpr, typeof(HttpResponse).GetProperty(nameof(HttpResponse.StatusCode))!);
|
|
|
- private static readonly ParameterExpression InvokedFilterContextExpr = Expression.Parameter(typeof(RouteHandlerInvocationContext), "filterContext");
|
|
|
|
|
|
|
+ private static readonly ParameterExpression InvokedFilterContextExpr = Expression.Parameter(typeof(EndpointFilterInvocationContext), "filterContext");
|
|
|
|
|
|
|
|
private static readonly string[] DefaultAcceptsContentType = new[] { "application/json" };
|
|
private static readonly string[] DefaultAcceptsContentType = new[] { "application/json" };
|
|
|
private static readonly string[] FormFileContentType = new[] { "multipart/form-data" };
|
|
private static readonly string[] FormFileContentType = new[] { "multipart/form-data" };
|
|
@@ -208,7 +208,7 @@ public static partial class RequestDelegateFactory
|
|
|
RouteParameters = options?.RouteParameterNames?.ToList(),
|
|
RouteParameters = options?.RouteParameterNames?.ToList(),
|
|
|
ThrowOnBadRequest = options?.ThrowOnBadRequest ?? false,
|
|
ThrowOnBadRequest = options?.ThrowOnBadRequest ?? false,
|
|
|
DisableInferredFromBody = options?.DisableInferBodyFromParameters ?? false,
|
|
DisableInferredFromBody = options?.DisableInferBodyFromParameters ?? false,
|
|
|
- FilterFactories = options?.RouteHandlerFilterFactories?.ToList(),
|
|
|
|
|
|
|
+ FilterFactories = options?.EndpointFilterFactories?.ToList(),
|
|
|
Metadata = options?.EndpointMetadata ?? new List<object>(),
|
|
Metadata = options?.EndpointMetadata ?? new List<object>(),
|
|
|
};
|
|
};
|
|
|
}
|
|
}
|
|
@@ -252,7 +252,7 @@ public static partial class RequestDelegateFactory
|
|
|
factoryContext.ServiceProvider,
|
|
factoryContext.ServiceProvider,
|
|
|
CollectionsMarshal.AsSpan(factoryContext.Parameters));
|
|
CollectionsMarshal.AsSpan(factoryContext.Parameters));
|
|
|
|
|
|
|
|
- RouteHandlerFilterDelegate? filterPipeline = null;
|
|
|
|
|
|
|
+ EndpointFilterDelegate? filterPipeline = null;
|
|
|
|
|
|
|
|
// If there are filters registered on the route handler, then we update the method call and
|
|
// If there are filters registered on the route handler, then we update the method call and
|
|
|
// return type associated with the request to allow for the filter invocation pipeline.
|
|
// return type associated with the request to allow for the filter invocation pipeline.
|
|
@@ -262,15 +262,15 @@ public static partial class RequestDelegateFactory
|
|
|
|
|
|
|
|
if (filterPipeline is not null)
|
|
if (filterPipeline is not null)
|
|
|
{
|
|
{
|
|
|
- Expression<Func<RouteHandlerInvocationContext, ValueTask<object?>>> invokePipeline = (context) => filterPipeline(context);
|
|
|
|
|
|
|
+ Expression<Func<EndpointFilterInvocationContext, ValueTask<object?>>> invokePipeline = (context) => filterPipeline(context);
|
|
|
returnType = typeof(ValueTask<object?>);
|
|
returnType = typeof(ValueTask<object?>);
|
|
|
- // var filterContext = new RouteHandlerInvocationContext<string, int>(httpContext, name_local, int_local);
|
|
|
|
|
|
|
+ // var filterContext = new EndpointFilterInvocationContext<string, int>(httpContext, name_local, int_local);
|
|
|
// invokePipeline.Invoke(filterContext);
|
|
// invokePipeline.Invoke(filterContext);
|
|
|
factoryContext.MethodCall = Expression.Block(
|
|
factoryContext.MethodCall = Expression.Block(
|
|
|
new[] { InvokedFilterContextExpr },
|
|
new[] { InvokedFilterContextExpr },
|
|
|
Expression.Assign(
|
|
Expression.Assign(
|
|
|
InvokedFilterContextExpr,
|
|
InvokedFilterContextExpr,
|
|
|
- CreateRouteHandlerInvocationContextBase(factoryContext)),
|
|
|
|
|
|
|
+ CreateEndpointFilterInvocationContextBase(factoryContext)),
|
|
|
Expression.Invoke(invokePipeline, InvokedFilterContextExpr)
|
|
Expression.Invoke(invokePipeline, InvokedFilterContextExpr)
|
|
|
);
|
|
);
|
|
|
}
|
|
}
|
|
@@ -298,7 +298,7 @@ public static partial class RequestDelegateFactory
|
|
|
return HandleRequestBodyAndCompileRequestDelegate(responseWritingMethodCall, factoryContext);
|
|
return HandleRequestBodyAndCompileRequestDelegate(responseWritingMethodCall, factoryContext);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- private static RouteHandlerFilterDelegate? CreateFilterPipeline(MethodInfo methodInfo, Expression? targetExpression, FactoryContext factoryContext, Expression<Func<HttpContext, object?>>? targetFactory)
|
|
|
|
|
|
|
+ private static EndpointFilterDelegate? CreateFilterPipeline(MethodInfo methodInfo, Expression? targetExpression, FactoryContext factoryContext, Expression<Func<HttpContext, object?>>? targetFactory)
|
|
|
{
|
|
{
|
|
|
Debug.Assert(factoryContext.FilterFactories is not null);
|
|
Debug.Assert(factoryContext.FilterFactories is not null);
|
|
|
// httpContext.Response.StatusCode >= 400
|
|
// httpContext.Response.StatusCode >= 400
|
|
@@ -314,10 +314,10 @@ public static partial class RequestDelegateFactory
|
|
|
// When `handler` returns an object, we generate the following wrapper
|
|
// When `handler` returns an object, we generate the following wrapper
|
|
|
// to convert it to `ValueTask<object?>` as expected in the filter
|
|
// to convert it to `ValueTask<object?>` as expected in the filter
|
|
|
// pipeline.
|
|
// pipeline.
|
|
|
- // ValueTask<object?>.FromResult(handler(RouteHandlerInvocationContext.GetArgument<string>(0), RouteHandlerInvocationContext.GetArgument<int>(1)));
|
|
|
|
|
|
|
+ // ValueTask<object?>.FromResult(handler(EndpointFilterInvocationContext.GetArgument<string>(0), EndpointFilterInvocationContext.GetArgument<int>(1)));
|
|
|
// When the `handler` is a generic Task or ValueTask we await the task and
|
|
// When the `handler` is a generic Task or ValueTask we await the task and
|
|
|
// create a `ValueTask<object?> from the resulting value.
|
|
// create a `ValueTask<object?> from the resulting value.
|
|
|
- // new ValueTask<object?>(await handler(RouteHandlerInvocationContext.GetArgument<string>(0), RouteHandlerInvocationContext.GetArgument<int>(1)));
|
|
|
|
|
|
|
+ // new ValueTask<object?>(await handler(EndpointFilterInvocationContext.GetArgument<string>(0), EndpointFilterInvocationContext.GetArgument<int>(1)));
|
|
|
// When the `handler` returns a void or a void-returning Task, then we return an EmptyHttpResult
|
|
// When the `handler` returns a void or a void-returning Task, then we return an EmptyHttpResult
|
|
|
// to as a ValueTask<object?>
|
|
// to as a ValueTask<object?>
|
|
|
// }
|
|
// }
|
|
@@ -333,13 +333,13 @@ public static partial class RequestDelegateFactory
|
|
|
: Expression.Assign(TargetExpr, Expression.Invoke(targetFactory, FilterContextHttpContextExpr)),
|
|
: Expression.Assign(TargetExpr, Expression.Invoke(targetFactory, FilterContextHttpContextExpr)),
|
|
|
handlerReturnMapping
|
|
handlerReturnMapping
|
|
|
);
|
|
);
|
|
|
- var filteredInvocation = Expression.Lambda<RouteHandlerFilterDelegate>(
|
|
|
|
|
|
|
+ var filteredInvocation = Expression.Lambda<EndpointFilterDelegate>(
|
|
|
Expression.Condition(
|
|
Expression.Condition(
|
|
|
Expression.GreaterThanOrEqual(FilterContextHttpContextStatusCodeExpr, Expression.Constant(400)),
|
|
Expression.GreaterThanOrEqual(FilterContextHttpContextStatusCodeExpr, Expression.Constant(400)),
|
|
|
CompletedValueTaskExpr,
|
|
CompletedValueTaskExpr,
|
|
|
handlerInvocation),
|
|
handlerInvocation),
|
|
|
FilterContextExpr).Compile();
|
|
FilterContextExpr).Compile();
|
|
|
- var routeHandlerContext = new RouteHandlerContext(
|
|
|
|
|
|
|
+ var routeHandlerContext = new EndpointFilterFactoryContext(
|
|
|
methodInfo,
|
|
methodInfo,
|
|
|
factoryContext.Metadata,
|
|
factoryContext.Metadata,
|
|
|
factoryContext.ServiceProvider ?? EmptyServiceProvider.Instance);
|
|
factoryContext.ServiceProvider ?? EmptyServiceProvider.Instance);
|
|
@@ -428,16 +428,16 @@ public static partial class RequestDelegateFactory
|
|
|
return ExecuteAwaited(task);
|
|
return ExecuteAwaited(task);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- private static Expression CreateRouteHandlerInvocationContextBase(FactoryContext factoryContext)
|
|
|
|
|
|
|
+ private static Expression CreateEndpointFilterInvocationContextBase(FactoryContext factoryContext)
|
|
|
{
|
|
{
|
|
|
// In the event that a constructor matching the arity of the
|
|
// In the event that a constructor matching the arity of the
|
|
|
// provided parameters is not found, we fall back to using the
|
|
// provided parameters is not found, we fall back to using the
|
|
|
- // non-generic implementation of RouteHandlerInvocationContext.
|
|
|
|
|
|
|
+ // non-generic implementation of EndpointFilterInvocationContext.
|
|
|
Expression paramArray = factoryContext.BoxedArgs.Length > 0
|
|
Expression paramArray = factoryContext.BoxedArgs.Length > 0
|
|
|
? Expression.NewArrayInit(typeof(object), factoryContext.BoxedArgs)
|
|
? Expression.NewArrayInit(typeof(object), factoryContext.BoxedArgs)
|
|
|
: Expression.Call(ArrayEmptyOfObjectMethod);
|
|
: Expression.Call(ArrayEmptyOfObjectMethod);
|
|
|
var fallbackConstruction = Expression.New(
|
|
var fallbackConstruction = Expression.New(
|
|
|
- DefaultRouteHandlerInvocationContextConstructor,
|
|
|
|
|
|
|
+ DefaultEndpointFilterInvocationContextConstructor,
|
|
|
new Expression[] { HttpContextExpr, paramArray });
|
|
new Expression[] { HttpContextExpr, paramArray });
|
|
|
|
|
|
|
|
if (!RuntimeFeature.IsDynamicCodeCompiled)
|
|
if (!RuntimeFeature.IsDynamicCodeCompiled)
|
|
@@ -453,17 +453,17 @@ public static partial class RequestDelegateFactory
|
|
|
|
|
|
|
|
var constructorType = factoryContext.ArgumentTypes?.Length switch
|
|
var constructorType = factoryContext.ArgumentTypes?.Length switch
|
|
|
{
|
|
{
|
|
|
- 1 => typeof(RouteHandlerInvocationContext<>),
|
|
|
|
|
- 2 => typeof(RouteHandlerInvocationContext<,>),
|
|
|
|
|
- 3 => typeof(RouteHandlerInvocationContext<,,>),
|
|
|
|
|
- 4 => typeof(RouteHandlerInvocationContext<,,,>),
|
|
|
|
|
- 5 => typeof(RouteHandlerInvocationContext<,,,,>),
|
|
|
|
|
- 6 => typeof(RouteHandlerInvocationContext<,,,,,>),
|
|
|
|
|
- 7 => typeof(RouteHandlerInvocationContext<,,,,,,>),
|
|
|
|
|
- 8 => typeof(RouteHandlerInvocationContext<,,,,,,,>),
|
|
|
|
|
- 9 => typeof(RouteHandlerInvocationContext<,,,,,,,,>),
|
|
|
|
|
- 10 => typeof(RouteHandlerInvocationContext<,,,,,,,,,>),
|
|
|
|
|
- _ => typeof(DefaultRouteHandlerInvocationContext)
|
|
|
|
|
|
|
+ 1 => typeof(EndpointFilterInvocationContext<>),
|
|
|
|
|
+ 2 => typeof(EndpointFilterInvocationContext<,>),
|
|
|
|
|
+ 3 => typeof(EndpointFilterInvocationContext<,,>),
|
|
|
|
|
+ 4 => typeof(EndpointFilterInvocationContext<,,,>),
|
|
|
|
|
+ 5 => typeof(EndpointFilterInvocationContext<,,,,>),
|
|
|
|
|
+ 6 => typeof(EndpointFilterInvocationContext<,,,,,>),
|
|
|
|
|
+ 7 => typeof(EndpointFilterInvocationContext<,,,,,,>),
|
|
|
|
|
+ 8 => typeof(EndpointFilterInvocationContext<,,,,,,,>),
|
|
|
|
|
+ 9 => typeof(EndpointFilterInvocationContext<,,,,,,,,>),
|
|
|
|
|
+ 10 => typeof(EndpointFilterInvocationContext<,,,,,,,,,>),
|
|
|
|
|
+ _ => typeof(DefaultEndpointFilterInvocationContext)
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
if (constructorType.IsGenericType)
|
|
if (constructorType.IsGenericType)
|
|
@@ -471,15 +471,15 @@ public static partial class RequestDelegateFactory
|
|
|
var constructor = constructorType.MakeGenericType(factoryContext.ArgumentTypes!).GetConstructors(BindingFlags.NonPublic | BindingFlags.Instance).SingleOrDefault();
|
|
var constructor = constructorType.MakeGenericType(factoryContext.ArgumentTypes!).GetConstructors(BindingFlags.NonPublic | BindingFlags.Instance).SingleOrDefault();
|
|
|
if (constructor == null)
|
|
if (constructor == null)
|
|
|
{
|
|
{
|
|
|
- // new RouteHandlerInvocationContext(httpContext, (object)name_local, (object)int_local);
|
|
|
|
|
|
|
+ // new EndpointFilterInvocationContext(httpContext, (object)name_local, (object)int_local);
|
|
|
return fallbackConstruction;
|
|
return fallbackConstruction;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // new RouteHandlerInvocationContext<string, int>(httpContext, name_local, int_local);
|
|
|
|
|
|
|
+ // new EndpointFilterInvocationContext<string, int>(httpContext, name_local, int_local);
|
|
|
return Expression.New(constructor, arguments);
|
|
return Expression.New(constructor, arguments);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // new RouteHandlerInvocationContext(httpContext, (object)name_local, (object)int_local);
|
|
|
|
|
|
|
+ // new EndpointFilterInvocationContext(httpContext, (object)name_local, (object)int_local);
|
|
|
return fallbackConstruction;
|
|
return fallbackConstruction;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -564,11 +564,11 @@ public static partial class RequestDelegateFactory
|
|
|
if (RuntimeFeature.IsDynamicCodeSupported)
|
|
if (RuntimeFeature.IsDynamicCodeSupported)
|
|
|
{
|
|
{
|
|
|
// Register expressions containing the boxed and unboxed variants
|
|
// Register expressions containing the boxed and unboxed variants
|
|
|
- // of the route handler's arguments for use in RouteHandlerInvocationContext
|
|
|
|
|
|
|
+ // of the route handler's arguments for use in EndpointFilterInvocationContext
|
|
|
// construction and route handler invocation.
|
|
// construction and route handler invocation.
|
|
|
// context.GetArgument<string>(0)
|
|
// context.GetArgument<string>(0)
|
|
|
// (string, name_local), (int, int_local)
|
|
// (string, name_local), (int, int_local)
|
|
|
- factoryContext.ContextArgAccess.Add(Expression.Call(FilterContextExpr, RouteHandlerInvocationContextGetArgument.MakeGenericMethod(parameters[i].ParameterType), Expression.Constant(i)));
|
|
|
|
|
|
|
+ factoryContext.ContextArgAccess.Add(Expression.Call(FilterContextExpr, EndpointFilterInvocationContextGetArgument.MakeGenericMethod(parameters[i].ParameterType), Expression.Constant(i)));
|
|
|
}
|
|
}
|
|
|
else
|
|
else
|
|
|
{
|
|
{
|
|
@@ -2126,7 +2126,7 @@ public static partial class RequestDelegateFactory
|
|
|
public Type[] ArgumentTypes { get; set; } = Array.Empty<Type>();
|
|
public Type[] ArgumentTypes { get; set; } = Array.Empty<Type>();
|
|
|
public Expression[] ArgumentExpressions { get; set; } = Array.Empty<Expression>();
|
|
public Expression[] ArgumentExpressions { get; set; } = Array.Empty<Expression>();
|
|
|
public Expression[] BoxedArgs { get; set; } = Array.Empty<Expression>();
|
|
public Expression[] BoxedArgs { get; set; } = Array.Empty<Expression>();
|
|
|
- public List<Func<RouteHandlerContext, RouteHandlerFilterDelegate, RouteHandlerFilterDelegate>>? FilterFactories { get; init; }
|
|
|
|
|
|
|
+ public List<Func<EndpointFilterFactoryContext, EndpointFilterDelegate, EndpointFilterDelegate>>? FilterFactories { get; init; }
|
|
|
public bool FilterFactoriesHaveRunWithoutModifyingPerRequestBehavior { get; set; }
|
|
public bool FilterFactoriesHaveRunWithoutModifyingPerRequestBehavior { get; set; }
|
|
|
|
|
|
|
|
public List<ParameterInfo> Parameters { get; set; } = new();
|
|
public List<ParameterInfo> Parameters { get; set; } = new();
|