After upgrading to MVC preview 5, I started seeing some of my Url.Action links break. After downloading the source and debugging into it, I discovered that Url.Action results in a call to RouteCollection.GetVirtualPath(viewContext, valuesDictionary). This
results in route parameter values from the *current* page being used to find map a route to a completely different action. It appears that GetVirtualPath looks at:
1. Values specified in the Url.Action call, then
2. Values specified in the request context for the current page, then
3. Default values for the route.
I don't understand #2. Why use parameters for current page A in a link to an action for page B? Is this by design? This caused real problems for me because I happen to have actions that take parameters of the same name, but different types... so not only
was it using wrong values, they weren't even of the right type.
the reason they say they did it is so that you can do <%= Url.Action( "Edit" ) %> and it will use the current controller and id etc but change the action to edit. But I would have preferred that this logic be moved out of the Routing engine and into MVC
so we can bypass it.
The Url it generates should not be based on the Url you're at!
One way to force this behaviour is to create a subclass of Route
public class FixedRoute : Route
{
public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
{
var newRequestContext = new RequestContext( requestContext.HttpContext, new RouteData() );
base.GetVirtualPath( newRequestContext, values );
}
}
Now you'll need to pass in ALL necessary values to GetVirtualPath. You'll also probably want to create some helper methods to copy values from the RouteData, to mimic the way it used to work. But now it's under your control.
remember to add FixedRoutes to your RouteTable instead of just Routes (so MapPath wont work any more)
RouteTable.Routes.Add( "name", new FixedRoute(...) )
Marked as answer by Eilon on Oct 07, 2008 07:21 PM
This behavior of Url.Action is quite inconsiderate. It will lead to a lot of head-scratching/hair-tearing for MVC users. At the very least, the developers of MVC should provide an alternate way to do this, such as being able to pass an optional bool parameter
to Url.Action to indicate if current routing data should be used or not.
bhamlin
0 Points
1 Post
Url.Action uses routeData values from current requestContext?
Oct 02, 2008 07:55 PM|LINK
After upgrading to MVC preview 5, I started seeing some of my Url.Action links break. After downloading the source and debugging into it, I discovered that Url.Action results in a call to RouteCollection.GetVirtualPath(viewContext, valuesDictionary). This results in route parameter values from the *current* page being used to find map a route to a completely different action. It appears that GetVirtualPath looks at:
1. Values specified in the Url.Action call, then
2. Values specified in the request context for the current page, then
3. Default values for the route.
I don't understand #2. Why use parameters for current page A in a link to an action for page B? Is this by design? This caused real problems for me because I happen to have actions that take parameters of the same name, but different types... so not only was it using wrong values, they weren't even of the right type.
tgmdbm
Contributor
4392 Points
883 Posts
ASPInsiders
MVP
Re: Url.Action uses routeData values from current requestContext?
Oct 04, 2008 08:25 PM|LINK
Thisis my biggest gripe with the routing engine.
the reason they say they did it is so that you can do <%= Url.Action( "Edit" ) %> and it will use the current controller and id etc but change the action to edit. But I would have preferred that this logic be moved out of the Routing engine and into MVC so we can bypass it.
The Url it generates should not be based on the Url you're at!
One way to force this behaviour is to create a subclass of Route
public class FixedRoute : Route
{
public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
{
var newRequestContext = new RequestContext( requestContext.HttpContext, new RouteData() );
base.GetVirtualPath( newRequestContext, values );
}
}
Now you'll need to pass in ALL necessary values to GetVirtualPath. You'll also probably want to create some helper methods to copy values from the RouteData, to mimic the way it used to work. But now it's under your control.
remember to add FixedRoutes to your RouteTable instead of just Routes (so MapPath wont work any more)
RouteTable.Routes.Add( "name", new FixedRoute(...) )
pilipinoy
Member
3 Points
4 Posts
Re: Url.Action uses routeData values from current requestContext?
Apr 23, 2009 10:29 AM|LINK