问题
I have recently started using attribute routing for my action methods and am struggling in getting the action name (and/or id) from the RouteData. Below is an example of how I use the attrubues like so:
[Route( "Edit/{id:int}" )]
public ActionResult Edit( int id )
{
...
}
Previously I used the following method as an extension of RouteData to retrieve the value
public static string GetActionName( this RouteData routeData )
{
return routeData.Values[ "Action" ] as string;
}
This used to return the action name (in this example "edit"). Now this alway returns null. An inspection of the RouteData dictionary shows that these values seem to no longer be placed in the root of the array but rather in an item keyed "[0] = "MS_DirectRouteMatches".
I am able to access this value in the following manner but due to my limited understanding of how these values are populated I am concerned that, for e.g. routes where there are more than one match, this code will fall over 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 the RouteData values populated by AttributeRouting?
回答1:
Your solution will work in all but one case. It is possible that a request will not match any route, so you should ensure the action
key exists before you return it, or you may 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;
}
That one case typically passes the request to IIS so it can return the 404 page (or a custom one if configured), and this basically just covers the custom 404 page case.
I would also change IList
to be IEnumerable
, since you are adding nothing to the list in the method.
There is no such thing as a request that matches more than one route (0 or 1 route are the only possibilities). In the case where there is no match, MS_DirectRouteMatches
will not exist. In the case where it does exist, there is 1 value in the collection.
Unfortunately, there aren't really any guarantees that the number of values in the collection won't change to more than one in a future version, but for now that holds true. But since there isn't a more robust way to determine an action name than this, it is what we are stuck with until the next breaking change.
来源:https://stackoverflow.com/questions/27245338/attributerouting-correct-way-of-getting-the-action-name-from-routedata