如何从URL或路径数据中获取控制器类型和操作信息?

时间:2010-04-22 12:38:51

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

在给定System.Web.Routing.RouteData的情况下,如何获取将要调用的控制器操作(方法)和控制器类型?

我的情况是这样的 - 我希望能够在OnActionExecuting方法中执行某些操作(或不执行)。

但是,我经常想知道当前的行动,而不是被称为“根”行动;通过这个我的意思是我可能有一个名为“登录”的视图,这是我的登录页面。该观点可能包括 另一个局部视图“LeftNav”。当为LeftNav调用OnActionExecuting时,我希望能够确定它是否真的被称为Login的“root”激活。

我意识到通过调用RouteTable.Routes.GetRouteData(actionExecutingContext.HttpContext),我可以获得“root”请求的路由,但是如何将其转换为 方法和类型信息?

到目前为止我唯一的解决方案是:

 var routeData = RouteTable.Routes.GetRouteData(actionExecutingContext.HttpContext)
 var routeController = (string)routeData.Values["controller"]; 
 var routeAction = (string)routeData.Values["action"];

这个问题是“routeController”是删除了“Controller”后缀的控制器名称,并不是完全限定的;即它是“登录”,而不是“MyCode.Website.LoginController”。

如果可能的话,我宁愿得到实际的TypeMethodInfo,或者至少是完全限定的类型名称。

任何想法或其他方法?

[编辑 - 这是ASP.Net MVC 1.0]

4 个答案:

答案 0 :(得分:5)

  protected override void OnActionExecuting(ActionExecutingContext filterContext)
  {
     var type1 = filterContext.Controller.GetType();
     var type2 = filterContext.ActionDescriptor
                    .ControllerDescriptor.ControllerType;
  }

好的,对不起,我错过了“根”部分。

然后,另一种方法,您可以将控制器类型保存到线程存储。伪代码:

  protected override void OnActionExecuting(ActionExecutingContext filterContext)
  {
     if (!Thread.LocalStorage.Contains("root_controller"))
        Thread.LocalStorage["root_controller"] = 
            filterContext.ActionDescriptor
                    .ControllerDescriptor.ControllerType;
  }

只是一个想法。我确信C#中提供了线程本地存储。这里的关键思想是你只为第一次请求保存它,因此它总是根控制器。

答案 1 :(得分:4)

这是我从各种来源编译的解决方案。 url 变量应包含操作的网址:

        url = "YOUR URL";
        // Original path is stored and will be rewritten in the end
        var httpContext = new HttpContextWrapper(HttpContext.Current);
        string originalPath = httpContext.Request.Path;

        try
        {
            // Fake a request to the supplied URL into the routing system
            httpContext.RewritePath(url);
            RouteData urlRouteData = RouteTable.Routes.GetRouteData(httpContext);

            // If the route data was not found (e.g url leads to another site) then authorization is denied.
            // If you want to have a navigation to a different site, don't use AuthorizationMenu
            if(urlRouteData != null)
            {
                string controllerName = urlRouteData.Values["controller"].ToString();
                string actionName = urlRouteData.Values["action"].ToString();

                // Get an instance of the controller that would handle this route
                var requestContext = new RequestContext(httpContext, urlRouteData);
                var controllerFactory = ControllerBuilder.Current.GetControllerFactory();
                var controller = (ControllerBase) controllerFactory.CreateController(requestContext, controllerName);

                // Find the action descriptor
                var controllerContext = new ControllerContext(httpContext, new RouteData(), controller);
                var controllerDescriptor = new ReflectedControllerDescriptor(controller.GetType());
                var actionDescriptor = controllerDescriptor.FindAction(controllerContext, actionName);
            }
        }
        finally
        {
            // Reset our request path.
            httpContext.RewritePath(originalPath);
        }

答案 2 :(得分:1)

public Type ControllerType(string controllerName)
{
   var fullName = controllerName + "Controller";
   var assemblyName = Assembly.GetExecutingAssembly().FullName;
   return Activator.CreateInstance(assemblyName, fullTypeName).GetType();
}

public MethodInfo ActionMethodInfo(string actionName, Type controllerType)
{
   return controllerType.GetMethod(actionName);
}

您是否在考虑与此类似的实施?需要一些尝试/捕获!!!

善,

答案 3 :(得分:0)

MvcSiteMapProvider这样做。这是这个特殊事物的代码。

Here is the code