ASP.NET Core Filter Factory示例解析及核心概念疑问求助
ASP.NET Core Endpoint Filter Factory 核心疑问解答
1. EndpointFilterFactoryContext 和 EndpointFilterDelegate 是什么?谁传入工厂函数?
- EndpointFilterFactoryContext:是过滤器工厂初始化阶段的上下文对象,包含当前端点的静态元数据(比如
MethodInfo、端点元数据集合等)。它的作用是让工厂在应用启动时就能获取端点的静态信息,判断是否需要生成对应的过滤逻辑(比如示例中通过MethodInfo获取方法参数)。 - EndpointFilterDelegate:是代表过滤器链中后续执行环节的委托——可能是下一个过滤器,也可能是端点本身的执行逻辑。它的作用和ASP.NET Core中间件里的
next委托类似,调用它就会把请求传递到下一个环节。
这两个参数由ASP.NET Core端点路由框架在应用启动阶段自动传入:当框架扫描并初始化所有端点(Controller Action、Minimal API端点等)时,如果某个端点关联了该Filter Factory,框架会自动构建EndpointFilterFactoryContext实例(填充当前端点的元数据),并把过滤器链中的下一个环节委托(next)传入,调用工厂函数生成最终的请求处理委托。
2. invocationContext 的来源?代码执行逻辑梳理
invocationContext 的来源
示例中的invocationContext是EndpointFilterInvocationContext类型的实例,它是请求执行阶段由框架创建的上下文对象,包含当前请求的所有动态信息:比如请求参数、HttpContext、端点信息等。每次请求到达该端点时,框架都会生成一个新的实例并传入到工厂返回的异步委托中。
完整执行逻辑分两个阶段:
阶段一:应用启动初始化(仅执行一次)
- 框架调用
ValidateIdFactory,传入当前端点的EndpointFilterFactoryContext和next委托 - 工厂通过
context.MethodInfo获取端点方法的所有参数,遍历查找名为id且类型为string的参数,记录其位置 - 如果找不到符合条件的参数,直接返回原
next委托,该过滤器对当前端点不生效 - 如果找到参数,返回一个新的异步委托,这个委托就是后续请求到来时要执行的过滤逻辑
阶段二:请求处理(每次请求到达时执行)
- 框架创建
EndpointFilterInvocationContext实例(即invocationContext),填充当前请求的参数、上下文等信息 - 执行工厂返回的异步委托:
- 通过
invocationContext.GetArgument<string>(idPosition.Value)获取请求中的id参数值 - 验证
id:如果为空/空字符串,或者不以s开头,直接返回Results.ValidationProblem结果,终止后续流程 - 如果验证通过,调用
next(invocationContext),将请求传递给下一个过滤器或端点本身,等待执行结果并返回
- 通过
示例代码
public static EndpointFilterDelegate ValidateIdFactory( EndpointFilterFactoryContext context, EndpointFilterDelegate next) { ParameterInfo[] parameters = context.MethodInfo.GetParameters(); int? idPosition = null; for (int i = 0; i < parameters.Length; i++) { if (parameters[i].Name == "id" && parameters[i].ParameterType == typeof(string)) { idPosition = i; break; } } if (!idPosition.HasValue) { return next; } return async (invocationContext) => { string id = invocationContext.GetArgument<string>(idPosition.Value); if (string.IsNullOrEmpty(id) || !id.StartsWith('s')) { return Results.ValidationProblem(new Dictionary<string, string[]> { { "id", new[] { "Id cannot be null or empty and must start with 's'" } } }); } return await next(invocationContext); }; }
内容的提问来源于stack exchange,提问作者yinivem462
相关产品推荐
相关产品推荐

