我能否从HttpContext获取控制器?

50

在给定HttpContext(或HttpContextBase)的情况下,是否有一种方法可以获取Controller的实例?


4
不,George Stocker 的回答已经是最接近的了。如果你想在 HttpContext 中保留对控制器的引用,可以通过在 IControllerFactory 实现中将引用添加到 HttpContext.Items 中来实现。 - smartcaveman
不是你的错,海报,但真让人恼火的是,每一个标题类似的SO帖子都没有关于如何实际获取控制器(实例)的答案。答案总是关于愚蠢的类和动作名称!!! - Post Impatica
不是你的错,海报,但是每一个标题类似的SO帖子都没有关于如何实际获取控制器(实例)的答案,真是令人恼火。答案总是关于愚蠢的类和动作名称! - undefined
4个回答

107

如果只想获得控制器名称而不是实例,就像在自定义授权覆盖AuthorizeCore(httpContext)时所需的那样,这是干净的代码。

var request = httpContext.Request;
var currentUser = httpContext.User.Identity.Name;
string controller = request.RequestContext.RouteData.Values["controller"].ToString();
string action = request.RequestContext.RouteData.Values["action"].ToString();

1
这并没有给出实际的方法名称。例如,如果操作名称在请求中隐含了。 - Abhishek Agrawal

32

HttpContext 将持有对 MvcHandler 的引用,MvcHandler 将持有对 RouteData 的引用,RouteData 将持有对特定路径正在调用的控制器的引用。

NB:这并不会给你实际的控制器,只是特定路径将要捕获的控制器。

GetController(HttpContextBase httpContext)
{
    var routeData = ((MvcHandler)httpContext.Handler).RequestContext.RouteData;

    var routeValues = routeData.Values;
    var matchedRouteBase = routeData.Route;
    var matchedRoute = matchedRouteBase as Route;

    if (matchedRoute != null)
    {
        Route = matchedRoute.Url ?? string.Empty;
    }

    AssignRouteValues(httpContext, routeValues);
}
protected virtual VirtualPathData getVirtualPathData(HttpContextBase httpContext, RouteValueDictionary routeValues)
{
    return RouteTable.Routes.GetVirtualPath(((MvcHandler)httpContext.Handler).RequestContext, routeValues);
}

private void AssignRouteValues(HttpContextBase httpContext, RouteValueDictionary routeValues)
{
    var virtualPathData = getVirtualPathData(httpContext, routeValues);

    if (virtualPathData != null)
    {
        var vpdRoute = virtualPathData.Route as Route;
        if (vpdRoute != null)
        {
            RouteDefaults = vpdRoute.Defaults;
            RouteConstraints = vpdRoute.Constraints;
            RouteDataTokens = virtualPathData.DataTokens;
            RouteValues = routeValues;
        }
    }
}

这段代码可能看起来很熟悉,因为我是从Phil Haack的路由调试器源代码进行了修改。


4
var currentRouteData = RouteTable.Routes.GetRouteData(new HttpContextWrapper(httpContext));
var currentController = currentRouteData.Values["controller"].ToString();
var currentAction = currentRouteData.Values["action"].ToString();

4
虽然这段代码片段可能解决了问题,但是包括解释真的有助于提高您的帖子质量。请记住,您正在为将来的读者回答问题,这些人可能不知道您提出代码建议的原因。 - yennsarah
谢谢建议。将在以后的帖子中实现。上面的代码是自解释的,我想它不需要解释。 - NidhinSPradeep
4
这个回答基本上是对比尔(Bill)之前回答的复制(而他的回答是在你回答4年前的)。 - bradlis7

1

不太容易,你基本上需要先从RouteData中获取MvcHandler,然后构建Controller。即使这样做,它也不会给你用于处理操作的实例,因为它将是控制器的新实例。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接