Search code examples
c#asp.netasp.net-mvcasp.net-mvc-routing

How can I get controller type and action info from a url or from route data?


How can I get the controller action (method) and controller type that will be called, given the System.Web.Routing.RouteData?

My scenario is this - I want to be able to do perform certain actions (or not) in the OnActionExecuting method for an action.

However, I will often want to know not the current action, but the "root" action being called; by this I mean I may have a view called "Login", which is my login page. This view may include another partial view "LeftNav". When OnActionExecuting is called for LeftNav, I want to be able to determine that it is really being called for the "root" aciton of Login.

I realise that by calling RouteTable.Routes.GetRouteData(actionExecutingContext.HttpContext), I can get the route for the "root" request, but how to turn this into method and type info?

The only solution I have so far, is something like:

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

The problem with this is that "routeController" is the controller name with the "Controller" suffix removed, and is not fully qualified; ie it is "Login", rather than "MyCode.Website.LoginController".

I would far rather get an actual Type and MethodInfo if possible, or at least a fully qualified type name.

Any thoughts, or alternative approaches?

[EDIT - this is ASP.Net MVC 1.0]


Solution

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

    OK, sorry, I missed the "root" part.

    Then, another way, you can save controller type to thread storage. Pseudocode:

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

    Just an idea. I'm sure thread local storage is available in C#. The key idea here is that you save it only for first request, thus it's always root controller.