You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Web API 2中,如何在Application_PostResolveRequestCache中确定要调用的Action?

解决在控制器创建前确定Web API调用Action的问题

核心问题分析

你需要在Application_PostResolveRequestCache阶段提前确定要调用的Action,以此选择对应的依赖注入实现,但当前创建的HttpControllerContext中RouteData为null——这是导致ApiControllerActionSelector.SelectAction无法正常工作的关键,因为Action选择逻辑严重依赖路由数据匹配控制器和Action的路由模板。

获取正确RouteData的方法

在Application_PostResolveRequestCache阶段,请求的路由已完成解析,可直接从HttpRequestMessage中获取路由数据,再手动赋值给HttpControllerContext:

修改CreateControllerContext方法

调整现有方法,添加RouteData赋值逻辑:

private static HttpControllerContext CreateControllerContext(
    HttpRequestMessage request,
    HttpControllerDescriptor controllerDescriptor
)
{
    HttpConfiguration configuration1 = controllerDescriptor.Configuration;
    HttpConfiguration configuration2 = request.GetConfiguration();
    if (configuration2 == null)
    {
        request.SetConfiguration(configuration1);
    }
    else if (configuration2 != configuration1)
    {
        request.SetConfiguration(configuration1);
    }

    HttpRequestContext httpRequestContext1 = request.GetRequestContext();
    // 从请求中获取已解析的RouteData
    var routeData = request.GetRouteData();
    var controller = (IHttpController)FormatterServices.GetUninitializedObject(controllerDescriptor.ControllerType);
    
    var controllerContext = new HttpControllerContext(httpRequestContext1, request, controllerDescriptor, controller);
    // 为ControllerContext赋值RouteData
    controllerContext.RouteData = routeData;
    
    return controllerContext;
}

完整的Action选择流程

  1. 获取控制器描述符:通过IHttpControllerSelector从请求中解析对应的HttpControllerDescriptor
  2. 创建带RouteData的ControllerContext:使用修改后的方法创建上下文
  3. 调用Action选择器:获取配置中的ApiControllerActionSelector实例,调用SelectAction得到目标Action

示例代码片段:

protected void Application_PostResolveRequestCache()
{
    var request = HttpContext.Current.Items["MS_HttpRequestMessage"] as HttpRequestMessage;
    if (request == null) return;

    var config = request.GetConfiguration();
    // 获取控制器选择器
    var controllerSelector = config.Services.GetHttpControllerSelector();
    var controllerDescriptor = controllerSelector.SelectController(request);
    
    // 创建带RouteData的ControllerContext
    var controllerContext = CreateControllerContext(request, controllerDescriptor);
    
    // 获取Action选择器并选择目标Action
    var actionSelector = config.Services.GetActionSelector();
    var actionDescriptor = actionSelector.SelectAction(controllerContext);
    
    // 根据actionDescriptor的信息(如ActionName、ControllerName等)选择对应的依赖注入实现
    // 此处添加你的依赖注入逻辑
}

注意事项

  • Application_PostResolveRequestCache阶段刚好是路由匹配完成、控制器创建之前的节点,完全符合你的需求场景
  • 若使用自定义路由或Action选择逻辑,需确保config.Services中注册的选择器是实际使用的实现,避免匹配不一致
  • 使用FormatterServices.GetUninitializedObject创建控制器实例时不会调用构造函数,不会触发依赖注入,契合你在注入前判断Action的需求

内容的提问来源于stack exchange,提问作者Matt Mills

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 05:43:20