【问题标题】:RequestContext - RouteData does not contain actionRequestContext - RouteData 不包含操作
【发布时间】:2015-03-16 15:29:32
【问题描述】:

所以我创建了自己的 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)
    {
    }

欢迎任何想法。

更新:

问题似乎与属性路由有关。虽然它在复制中运行良好,但对我来说在生产中不起作用。

一路上发现了这个 - 一旦this 得到答复,我想我也会有我的正确解决方案。

更新 2:

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

【问题讨论】:

  • 有什么问题? requestContext.RouteData.Values["action"] 是否返回 null
  • 是的。取决于 mvc 版本

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


【解决方案1】:

我可以确认在 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();

顺便说一句-在您提供的linked question 中,提问者假设请求可能匹配多个路由。但这是不可能的 - 一个请求将匹配 0 或 1 个路由,但不会超过一个。

【讨论】:

  • 关闭原因:设计使然。哇。那是懒惰。显然没有按预期工作......是的。我也应用了这种解决方法
猜你喜欢
  • 2016-07-13
  • 2022-12-21
  • 1970-01-01
  • 1970-01-01
  • 2011-02-20
  • 2011-09-30
  • 1970-01-01
相关资源
最近更新 更多