1

I’ve got the following code (from a partial view), which creates a list of links enabling me to filter the items listed within my index page according to the letter they begin with:

@{
    string letters = "abcdefghijklmnopqrstuvwxyz";
}
<ul>
    <li>@Html.ActionLink("0–9", "Index")</li>
    @foreach (char c in letters.ToCharArray()) {
        <li>@Html.ActionLink(c.ToString().ToUpper(), "Index", new { letter = c.ToString() })</li>
    }
</ul>

The first link in the list is for cases where the items begin with a number. I’ve also got the following routes set up in my Global.asax file:

routes.MapRoute(
    "",
    "artists",
    new { controller = "Artist", action = "Index" }
);

routes.MapRoute(
    "",
    "artists/{letter}",
    new { controller = "Artist", action = "Index" },
    new { letter = "[a-z]" }
);

So the paths for the links that the above partial view creates should look something like:

/artists
/artists/a
/artists/b
…

and so on. What I’m getting though is odd in that it’s ignoring the routing and creating links like:

/artists
/artists?letter=a
/artists?letter=b
…

Now, if I swap around the order of the routes, it produces the links as I want them, but then I run into another problem. If I then navigate to /artists/a (or any other letter), the first link in the list picks up the current value of the letter parameter and appends it to the list, so I end up with links like:

/artists/a
/artists/a
/artists/b
…

As you can see, that makes it impossible to get back to the index with no filtering. Any ideas as to how I can either fix the routing so that the links are created correctly without the parameters being passed as a query string, or fix the ActionLink as to not append the current parameter?

Dylan Parry
  • 3,373
  • 6
  • 26
  • 38

1 Answers1

1

Make only one route and set the {letter} parameter as optional.

routes.MapRoute(
    "artists",
    "artists/{letter}",
    new { controller = "Artist", action = "Index", letter = UrlParameter.Optional },
    new { letter = "[a-z]" }
);

EDIT:

Have a look at this post.

EDIT2:

Another possible solution would be:

routes.MapRoute(
    "artists",
    "artists/{letter}",
    new { controller = "Artist", action = "Index", letter = "0" },
    new { letter = "[0a-z]" }
);

@Html.ActionLink("0–9", "Index", new { letter = "0"} );
Community
  • 1
  • 1
DanielB
  • 19,910
  • 2
  • 44
  • 50
  • Thanks. I’ve tried that, but then the route “/artists” doesn’t get matched as the constraint for the letter parameter means that route doesn’t match. If I change it to [a-z]? it matches, but then I have the same problem with the first route picking up the current value of the letter parameter. – Dylan Parry Jun 08 '11 at 08:06
  • try to make the constrain `([a-z])?` to allow an empty value. – DanielB Jun 08 '11 at 08:12
  • @DanielB, I’ve tried that too. It then matches the “/artists” route correctly, but creates links where the parameters are appended as a query string instead of like “/artists/a”. – Dylan Parry Jun 08 '11 at 08:29
  • Had a look at the post you linked, and whilst that allows the routes to match, it still creates links incorrectly with ActionLink as the first link is still picking up the letter params current value. – Dylan Parry Jun 08 '11 at 08:31
  • give this a try `@Html.ActionLink("0-9", "Index", new { letter = null })`. – DanielB Jun 08 '11 at 08:48
  • That gives an error in VS: “Cannot assign to anonymous type property”. I tried casting the null vale to a “char?”, which then allows me to run the page at least, but I still get the current letter param value appended to the link as a query string. Seems the current value overrides the null value. – Dylan Parry Jun 08 '11 at 09:12
  • Edit two does appear to work :) At first I thought it’d create a URL like “/artists/0”, but it appears to create a simple “/artists” URL. Thanks! – Dylan Parry Jun 08 '11 at 09:21