Search code examples
asp.netasp.net-mvc-5asp.net-mvc-routinghttpmoduleattributerouting

route.GetRouteData(httpContext).Values["action"] is null for Attribute Routing


What I'm trying to do it to get the controller name and action name in an HttpModule.

In the OnBeginRequest of my http module, I have the following code:

foreach (var route in RouteTable.Routes)
{
    if (route.GetRouteData(httpContext) != null)
    {
        Console.WriteLine(string.Format(CultureInfo.InvariantCulture, 
            "Route info ====== {0}, {1} ======", 
            route.GetRouteData(httpContext).Values["controller"], 
            route.GetRouteData(httpContext).Values["action"]));
    }
}

If the route is register using conventional routing like this:

routes.MapRoute("BlogDetails", "blog/{blogId}", new { controller = "Blog", action = "Details" });

And when I go to: ~/blog/1 I could see the output

"Route info ====== Blog, Details ======"

But if it's register using:

routes.MapMvcAttributeRoutes();

And in the controller I have:

[RouteArea("blog", AreaPrefix = "blog")]
[Route("{action}")]

On the action I have:[Route("{blogId}", Name="blogDetailRoute")]

And when I go to: ~/blog/1 I only see the output

"Route info ====== Blog,  ======"

The action name is missing in that route data.

Anything is different in the attribute routing? Where could I find the action name?

Thanks for helping out!


Solution

  • The routes for attribute routing are stored in a nested IEnumerable<RouteData> named MS_DirectRouteMatches.

    var routeData = routes.GetRouteData(httpContext);
    if (routeData != null)
    {
         if (routeData.Values.ContainsKey("MS_DirectRouteMatches"))
         {
              routeData = ((IEnumerable<RouteData>)routeData.Values["MS_DirectRouteMatches"]).First();
         }
    }
    

    This example shows how we take the regular route data if it matches the current context, and replace it with attribute routing data if it happens to exist.