Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to ignore current route values when generating links?

The question is similar to asp.net mvc Html.ActionLink() keeping route value I don't want, but with a twist that makes it more complex.

Starting from a default new MVC3 app, I change the routes to:

routes.MapRoute(
    "r1", // Route name
    "{controller}/{id}/{action}"
);

routes.MapRoute(
    "r2", // Route name
    "{controller}/{action}"
);

Notice that the id comes before the action in the first.

Then in Home\Index.cshtml, I add:

@Url.Action("Index")
@Url.Action("Index", new { id = "blah" })
@Url.Action("Index", new { id = "" })

Now I navigate to /Home/Foo/Index and look at the 3 generated links. I get

  1. "/Home/Foo/Index"
  2. "/Home/blah/Index"
  3. "/Home/Index?id=Foo"

The first two make sense, and are using the first route.

But in the third link, which hits the second route, I don't understand why id=Foo is passed on the query string, given that I explicitly passed an empty id. I would expect it to just generate "/Home/Index".

Can anyone explain that, and suggest how I can get it not to show up?

like image 757
David Ebbo Avatar asked Jun 30 '11 05:06

David Ebbo


People also ask

What is Route constraint?

You use route constraints to restrict the browser requests that match a particular route. You can use a regular expression to specify a route constraint. For example, imagine that you have defined the route in Listing 1 in your Global. asax file.

What are route values?

Route values are the values extracted from a URL based on a given route template. Each route parameter in a template will have an associated route value and is stored as a string pair in a dictionary.

What is Route attribute?

As the name implies, attribute routing uses attributes to define routes. Attribute routing gives you more control over the URIs in your web API. For example, you can easily create URIs that describe hierarchies of resources. The earlier style of routing, called convention-based routing, is still fully supported.


4 Answers

I just tested this and it seems to work ok.

Url.Action("Index", new { id = UrlParameter.Optional })

generates

/Home/Index
like image 195
PabloBlamirez Avatar answered Sep 28 '22 17:09

PabloBlamirez


This is probably not the answer you're looking for, but using Url.Route instead of Url.Action seems to work:

@Url.RouteUrl("r2")

This generates /Home/Index

Update

Phil Haack recommendeds generating URLs using the route name:

This might seem like a big problem, but the fix is actually very simple. Use names for all your routes and always use the route name when generating URLs. Most of the time, letting routing sort out which route you want to use to generate an URL is really leaving it to chance. When generating an URL, you generally know exactly which route you want to link to, so you might as well specify it by name.

like image 27
Daniel Liuzzi Avatar answered Sep 28 '22 16:09

Daniel Liuzzi


To solve it in this case is quite easy if yo don't care how it's solved.

Change the third link to:

@Url.RouteUrl("R2")

which gives me:

  • /Home/Foo/Index
  • /Home/blah/Index
  • /Home/Index

Why it happends in the first case is something I have yet to figure out. I have been bitten by this too but mostly when it comes to forms.

UPDATE 1:

I was digging around the MVC source and created a few tests that reproduced this problem. The problem seems to be when

RouteCollection.GetVirtualPath(requestContext, correctedValues);

is run. It creates a querystring with the old id. Exactly why I couldn't tell as that class isn't located in the MVC source.

like image 37
Mikael Eliasson Avatar answered Sep 28 '22 16:09

Mikael Eliasson


Because r2 does not define the id parameter to be a part of the URL? If you change it to {controller}/{action}/{id}, it will be fine. You'll see the same behaviour if you change r2 to not include action: action will then also becoe a query variable.

The fact that you explicitly set it to "" means that routing will take it into account anyway. Just don't add id and you'll be fine when generating a link.

like image 24
maartenba Avatar answered Sep 28 '22 17:09

maartenba