Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting area, controller and action names inside filter attributes

I have global attribute in which i need to know the area, controller and action. I can't use RawUrl due to routes (inside area registration and attribute routing). I have followed the following two approaches but in both cases, my area is coming back as null. When i use a route then i get the area name just fine. Why is my area null when i do redirecttoaction or url.action or type the url manually etc? We are using MVC 5.0.

1:

var routingValues = RouteTable.Routes.GetRouteData(new HttpContextWrapper(HttpContext.Current)).Values;

                        var currentArea = (string) routingValues["area"] ?? string.Empty;
                        var currentController = (string) routingValues["controller"] ?? string.Empty;
                        var currentAction = (string) routingValues["action"] ?? string.Empty;

2:

var handler = HttpContext.Current.Handler as System.Web.Mvc.MvcHandler;
                            var area = handler.RequestContext.RouteData.Values["area"];
                            var controller = handler.RequestContext.RouteData.Values["controller"];
                            var action = handler.RequestContext.RouteData.Values["action"];

Like i said above, if i use a route (/TipHotLine) then i get the area name just fine.

public class AgencyAreaRegistration : AreaRegistration 
    {
        public override string AreaName 
        {
            get 
            {
                return "Agency";
            }
        }

        public override void RegisterArea(AreaRegistrationContext context) 
        {
            context.MapRoute(
                "Agency_default",
                "Agency/{controller}/{action}/{id}",
                new { action = "Index", id = UrlParameter.Optional }
            );

            context.MapRoute(
                "tiphotline",
                "tiphotline",
                new
                {
                    controller = "tiphotline",
                    action = "Index",
                    Area = "Agency"
                }
            );


        }
    }
like image 624
learning... Avatar asked Mar 17 '23 03:03

learning...


1 Answers

When an area is registered the MapRoute method used is adding a dataContextToken to each route. You can check the source code here, you will see a method like the following and you will notice a line adding the data token:

public Route MapRoute(string name, string url, object defaults, object constraints, string[] namespaces)
{
    ...   
    route.DataTokens[RouteDataTokenKeys.Area] = AreaName;
    ...
    return route;
}

So in your filter you just need to get the data token with key "area" instead of a route value. For example the following filter will add a header the area, controller, and action found in the route

public override void OnActionExecuting(ActionExecutingContext filterContext)
{
    var routingValues = filterContext.RouteData.Values;
    var currentArea = filterContext.RouteData.DataTokens["area"] ?? string.Empty;
    var currentController = (string)routingValues["controller"] ?? string.Empty;
    var currentAction = (string)routingValues["action"] ?? string.Empty;

    filterContext.HttpContext.Response.AddHeader("Routing info", string.Format("controller={0},action={1},area={2}", currentController, currentAction, currentArea));
}
like image 103
Daniel J.G. Avatar answered Mar 19 '23 17:03

Daniel J.G.