AttributeRouting is the correct way to get action name from RouteData

I recently started using attribute routing for my action methods and am struggling to get the action name (and / or id) from RouteData. Below is an example of how I use attrubues like this:

[Route( "Edit/{id:int}" )]
public ActionResult Edit( int id )
{
    ...
}

      

I have previously used the following method as a RouteData extension to retrieve the value

public static string GetActionName( this RouteData routeData )
{
    return routeData.Values[ "Action" ] as string;
}

      

This is used to return the name of the action (in this example "edit"). Now this always returns null. Checking the RouteData dictionary shows that these values ​​no longer fit in the root of the array, but rather in the element with key "[0] =" MS_DirectRouteMatches ".

I can access this value as follows, but due to my limited understanding of how these values ​​are populated, I am concerned that, for example, routes where there is more than one match, this code will fail in some cases.

public static string GetActionName( this RouteData routeData )
{
    if( routeData.Values.ContainsKey( "MS_DirectRouteMatches" ) )
        routeData = ( ( IList<RouteData> )routeData.Values[ "MS_DirectRouteMatches" ] )[ 0 ];

    return routeData.Values[ "Action" ] as string;
}

      

What is the correct way to access RouteData values ​​filled with AttributeRouting?

+3


source to share


1 answer


Your solution will work in all but one case. It is possible that the request will not match any route, so you must make sure the key action

exists before you return it, or you might get an exception.

public static string GetActionName( this RouteData routeData )
{
    if( routeData.Values.ContainsKey( "MS_DirectRouteMatches" ) )
        routeData = ( ( IEnumerable<RouteData> )routeData.Values["MS_DirectRouteMatches"] )[0];

    return routeData.Values.ContainsKey("action") ? 
        routeData.Values["action"] as string : 
        string.Empty;
}

      

This case usually passes the request to IIS so that it can return a 404 page (or a custom one if it has been customized) and this mostly only applies to a custom 404 page case.



I would also change IList

how IEnumerable

, since you are not adding anything to the list in this method.

There is no such thing as a request that matches multiple routes (the only possibilities are 0 or 1 route). In the absence of a match, MS_DirectRouteMatches

it will not exist. In case it exists, there is 1 value in the collection.

Unfortunately, there is actually no guarantee that the number of values ​​in the collection will not change by more than one in a future version, but this is true for now. But since there is no more reliable way to determine the name of an action than this, this is where we get stuck until the next violation.

+1


source







All Articles