RequestContext - RouteData不包含操作

时间:2015-03-16 15:29:32

标签: asp.net-mvc asp.net-mvc-routing

所以我创建了自己的ControllerFactory,并且我正在重载GetControllerSessionBehavior以扩展MVC行为。

要做我的自定义工作,我必须对被调用的动作使用反射。然而,我偶然发现了一个奇怪的问题 - 我无法通过访问RequestContext.RouteData来检索操作

在为此设置复制样本时,我无法重现错误。

是否有人知道可能的原因或知道如何通过调用除此之外的请求上下文的方法来检索操作?

public class CustomControllerFactory : DefaultControllerFactory
{
    protected override SessionStateBehavior GetControllerSessionBehavior(RequestContext requestContext, Type controllerType)
    {
        if (!requestContext.RouteData.Values.ContainsKey("action"))
            return base.GetControllerSessionBehavior(requestContext, controllerType);

        var controllerAction = requestContext.RouteData.Values["action"];
        var action = controllerAction.ToString();

        var actionMethod = controllerType.GetMember(action, MemberTypes.Method, BindingFlags.Instance | BindingFlags.Public).FirstOrDefault();
        if(actionMethod == null)
            return base.GetControllerSessionBehavior(requestContext, controllerType);

        var cattr = actionMethod.GetCustomAttribute<SessionStateActionAttribute>();
        if (cattr != null)
            return cattr.Behavior;

        return base.GetControllerSessionBehavior(requestContext, controllerType);
    }
}

我可以调用的操作很好但无法访问我的控制器工厂中的操作名称:

    [Route("Open/{createModel:bool?}/{tlpId:int}/{siteId:int?}")]
    public ActionResult Open(int tlpId, int? siteId, bool? createModel = true)
    {
    }

欢迎任何想法。

更新

问题似乎与属性路由有关。虽然它在repro中工作正常但它对我来说不适用于生产。

在此过程中发现了这一点 - 一旦this得到解答,我也会得到正确的解决方案。

更新2:

有趣。复制MVC版本5.0.0.0,制作5.2.2。可能引入bug?

1 个答案:

答案 0 :(得分:6)

我可以确认5.0.0和5.1.1之间的属性路由发生了重大变化。我报告了问题here。但是,对于我的用例,Microsoft能够提供可接受的解决方法。

另一方面,你遇到的问题看起来像是另一个罪魁祸首。对于属性路由,路由值存储在名为MS_DirectRouteMatches嵌套路由密钥中。我不确定改变了哪个版本,但我知道它发生了v5 +。

因此,要解决您的问题,您需要检查是否存在嵌套的RouteData集合,并在存在的情况下使用而不是正常的RouteData。

var routeData = requestContext.RouteData;
if (routeData.Values.ContainsKey("MS_DirectRouteMatches"))
{
    routeData = ((IEnumerable<RouteData>)routeData.Values["MS_DirectRouteMatches"]).First();
}
var controllerAction = routeData.Values["action"];
var action = controllerAction.ToString();

BTW - 在您提供的linked question中,提问者认为请求可能匹配多条路线。但这是不可能的 - 请求将匹配0或1路由,但绝不会超过一个。