RequestContext - RouteData不包含操作

Dbl*_*Dbl 2 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

欢迎任何想法.

更新:

问题似乎与属性路由有关.虽然它在repro中运行良好但它对我来说不适用于生产.

途中发现这一点-一旦这个被回答,我将拥有妥善的解决办法太我猜.

更新2:

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

Nig*_*888 6

我可以确认5.0.0和5.1.1之间的属性路由发生了重大变化.我在这里报道了这个问题.但是,对于我的用例,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();
Run Code Online (Sandbox Code Playgroud)

顺便说一句 - 在你提供的链接问题中,提问者认为请求可能匹配多条路由.但这是不可能的 - 请求将匹配0或1路由,但绝不会超过一个.