views:

380

answers:

3

I have an action called List that shows the results of a search. It receives parameters through the querystring because they are optional. My method signature looks like this:

public ActionResult List(List<int> categoryIDs, string school, int? stateID, int? page)

CategoryIDs is a multi-select box and I am doing everything over a GET request. What I need to do is create a link in my view to the next page but retain the same search parameters. I know I can build the link by hand but it is possible to use any of the built-in routing method especially when the categoryIDs have to be formatted like "?categoryID=1&categoryID=2&categoryID=3" to be bound to the list?

A: 

You should be able to do this:

<%= Html.ActionLink("Link Text", "List", new {page = 2}) %>

All the current values should be passed in by default. I'd have to try it out though to make sure I'm referencing the correct overload.

Haacked
Jonathan
@Haacked, you know they are re-making the movie in your avatar? Samuel L Jackson will play that dude.
Simucal
I ended up having to just bind it by hand by looking at Request.Querystring and splitting it as Buu pointed out. This way, it works when there are multiple categoryID params or CSV. Is this behavior a bug or by design?
Jonathan
Oh, I didn't realize you wanted all the other parameters passed as query strings. We don't pass "ambient" values to the query string. They have to be defined as part of the route.@Simulcal - yes, I've heard. It'll be awesome!
Haacked
A: 

I think there's no ActionLink overload that helps you do that by default. You need to populate the RouteValueDictionary instance with the parameters you want to include.

For the list of category, try s/t like categoryIDs=2,3,4,5 etc. since repeating keys are not allowed in RouteValueDictionary. After that, in the action method will need to parse the string into the integer list.

Buu Nguyen
I tried this. When the parameter is n the format of categoryIDs=2,3,4,5 it doesn't get bound to the List<int> in the action method signature. Evidently the only way that gets bound is with a repeating parameter. If all else fails, I could create a new action that takes a string in that spot.
Jonathan
That's what I said - the action method will need to parse the string into the integer list. That is, you have to write the code to do that in the action method since I don't think ASP.NET MVC automatically bind that to the parameter.
Buu Nguyen
A: 

I like to pass an object as a parameter to search actions, and then pass the parameter object to the view. So with some code in your controller like this (note I'm using Rob Conery's PagedList class):

public class SearchParameters {
    public string School { get; set; }
    public int? StateID { get; set; }
    public int? Page { get; set; }

    public SearchParameters GetPage(int page) {
        return new SearchParameters {
            School = School,
            StateID = StateID,
            Page = page
        };
    }
}

public class SearchViewModel {
    public PagedList<[YourResultType]> Results { get; set; }
    public SearchParameters Parameters { get; set; }
}

// ...

public ActionResult Search(SearchParameters parameters) {
    IQueryable<[YourResultType]> query;
    // ... do some stuff to get your search results

    return View("Search", new SearchViewModel {
        Results = query.ToPagedList(parameters.Page - 1), 15),
        Parameters = parameters
    });
}

So your search view inherits from the generic ViewPage<T> with a page declaration like this:

<%@ Page ... Inherits="ViewPage<SearchViewModel>" %>

Then in your search view, you can do something like this...

<% for(int i = 0; i < Model.Results.TotalPages; i++) { %>
    <%= Html.ActionLink(i + 1).ToString(), "Search",
        Model.Parameters.GetPage(i + 1)) %>
<% } %>
Luke Sampson