RequestContext-RouteData不包含操作 [英] RequestContext - RouteData does not contain action

查看:149
本文介绍了RequestContext-RouteData不包含操作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

因此,我创建了自己的ControllerFactory,并重载了GetControllerSessionBehavior,以扩展MVC行为.

So i've created my own ControllerFactory and i'm overloading GetControllerSessionBehavior in order to extend the MVC behavior.

要执行我的自定义工作,我必须在被调用的动作上使用反射.但是我偶然发现了一个奇怪的问题-我无法通过访问RequestContext.RouteData

To do my custom work i have to use reflection on the called action. However i've stumbled upon a weird issue - i can't retrieve the action by accessing RequestContext.RouteData

为此设置复制样本时,我无法复制该错误.

While setting up a reproduction sample for this i was not able to reproduce the error.

是否有人知道这种情况的可能原因,或者是否知道如何通过使用请求上下文以外的方法调用方法来检索操作?

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);
    }
}

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

Action which i can call just fine but can't access the action name of within my controller factory:

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

欢迎提出任何想法.

更新:

该问题似乎与属性路由有关.尽管可以正常复制,但对我而言却无法正常生产.

The problem seems to be related to attribute routing. While it's working fine in repro it doesn't work in production for me.

一路走来发现了这一点-一次回答,我想我也会有适当的解决方案.

Found this along the way - Once this is answered i'll have my proper solution too i guess.

更新2:

有趣.复制MVC版本5.0.0.0,生产5.2.2.可能会引入错误?

Interesting. Reproduction MVC Version 5.0.0.0, Production 5.2.2. Possible introduction of bug?

推荐答案

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

I can confirm that there was a breaking change to attribute routing between 5.0.0 and 5.1.1. I reported the issue here. However, for my use case Microsoft was able to provide an acceptable workaround.

另一方面,您遇到的问题似乎是另一个罪魁祸首.对于属性路由,路由值存储在名为MS_DirectRouteMatches嵌套路由键中.我不确定确切会更改哪个版本,但我知道它发生在v5 +.

On the other hand, the problem you are bumping into looks like another culprit. For attribute routing, the route values are stored in a nested route key named MS_DirectRouteMatches. I am not sure exactly which version that changed in, but I know it happened v5+.

因此,要解决您的问题,您将需要检查嵌套RouteData集合的存在,并在存在的情况下使用常规RouteData代替它.

So, to fix your issue, you will need to check for the existence of a nested RouteData collection, and use instead of the normal RouteData in the case it exists.

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-在链接的问题您已提供,询问者认为请求有可能匹配多个路径.但这是不可能的-请求将匹配0或1条路由,但不会超过一个.

BTW - In the linked question you provided, the asker assumed that there is a possibility where a request can match more than one route. But that is not possible - a request will match 0 or 1 route, but never more than one.

这篇关于RequestContext-RouteData不包含操作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆