views:

135

answers:

3

I have a list of puzzles that are tagged with specific "Themes". Think questions on stackoverflow tagged with certain categories.

I'm trying to get my route setup so that it works like this:

http://www.wikipediamaze.com/puzzles/themed/Movies http://www.wikipediamaze.com/puzzles/themed/Movies,Another-Theme,And-Yet-Another-One

My routes are setup like this:

    routes.MapRoute(
        "wiki",
        "wiki/{topic}",
        new {controller = "game", action = "continue", topic = ""}
        );

    routes.MapRoute(
        "UserDisplay",
        "{controller}/{id}/{userName}",
        new {controller = "users", action = "display", userName=""},
        new { id = @"\d+" }
        );

    routes.MapRoute(
        "ThemedPuzzles",
        "puzzles/themed/{themes}",
        new { controller = "puzzles", action = "ThemedPuzzles", themes = "" }
        );

    routes.MapRoute(
        "Default", // Route name
        "{controller}/{action}/{id}", // URL with parameters
        new {controller = "Home", action = "Index", id = ""} // Parameter defaults
        );

My Controller looks like this:

public ActionResult ThemedPuzzles(string themes, PuzzleSortType? sortType, int? page, int? pageSize)
{
    //Logic goes here
}

My Action link call in the views looks like this:

        <ul>
        <%foreach (var theme in Model.Themes)
          { %>
            <li><%=Html.ActionLink(theme, "themed", new {controller = "puzzles", themes = theme})%></li>
            <% } %>
        </ul>

However the problem I'm having is this:

The links that get generated show up like this:

http://www.wikipediamaze.com/puzzles/themed?themes=MyThemeNameHere

To add to this problem the "Themes" parameter on the controller action always comes through as null. It never translates the querystring parameter to the controller action parameter. However, if I manually navigate to

http://www.wikipediamaze.com/puzzles/themed/MyThemeNameHere http://www.wikipediamaze.com/puzzles/themed/MyThemeNameHere,Another-ThemeName

everything works just fine. What am I missing?

Thanks in advance!

A: 

Try this:

<li><%=Html.ActionLink(theme, "themed", new {controller = "puzzles", **action="ThemedPuzzles"** themes = theme})%></li>

You need to specify action because you have a default for action but there's no {action} parameter in your URL. The reason for this behavior is suppose have another route like

routes.MapRoute(
        "SpecialThemedPuzzles",
        "puzzles/special-themed/{themes}",
        new { controller = "puzzles", action = "SpecialThemedPuzzles", themes = "" }
        );

How would you generate a URL to this route? You wouldn't be able to unless we had some way to distinguish this route from your other theme route. So in this case, when Routing sees a parameter in the defaults dictionary that is not a parameter in the actual URL, it requires that you specify that value to distinguish between the two routes.

In this case, it requires you specify the action to distinguish between the routes.

Haacked
That's still not working. Should I being doing this completely different than the way I'm trying?
Micah
+1  A: 

The actionName parameter (second parameter) of your call to Html.ActionLink doesn't match the action you've specified in your "ThemedPuzzles" route.

Very similar to Phil's suggestion, try:

<%= Html.ActionLink(theme, "ThemedPuzzles", new { controller = "puzzles", themes = theme }) %>

Or you can call to the route directly (since it's named) without needing to specify the controller or action (as they'll be picked up from the route defaults):

<%= Html.RouteLink(theme, "ThemedPuzzles", new { themes = theme }) %>
itsmecurtis
A: 

In your route declaration, try specifying every input parameter in your controller method.

routes.MapRoute(        
"ThemedPuzzles",        
"puzzles/themed/{themes}",        
new { controller = "puzzles", action = "ThemedPuzzles", themes = "",  sortType = "", page="", pageSize="" }        
);

If you have defaults for the sort type, the page number, and the page size, you could even set them here so if they are not included, a default is passed in.

Josh
It's not necessary to provide each input parameter in your route declaration -- because the sortType, page, and pageSize parameters are all nullable they need only be specified if you want to give any of them a default value.
itsmecurtis
You are right, but in my personal experience if you want the URL to be in the friendly folder structure rather than using the querystring, you need to define all the parts. It's how I've always fixed it.
Josh