views:

1043

answers:

3

Hi,

I'm currently working on a reasonably simple MVC app which allows the user to enter some search data, get a list of results, then view each item etc. It's all going rather nicely, however I'm now trying to implement paging but having some trouble.

My search form uses HTTP GET, requesting the following action:

public ActionResult Results(PropertySearchData data, int? page)
{
    ...
    IEnumerable<Property> search = mService.SearchProperties(data);

    ViewData["SearchData"] = data;
    return View("Results", "Site", search.ToPagedList(page ?? 0, 20));
    ...
}

From here I build my table of results from the IEnumerable collection passed into my view. In addition, I've used ViewData to hold the search parameters so that I can pass them on when the user requests a different page.

For example, to get to the first page, I'd like to use something like this:

Html.ActionLink("First", "Results", new { data = ViewData["SearchData"], page = 1 })

However, when this link is generated, my link is along the lines of

/Results?data=PropertySearchData&page=1

If I remove the 'page' parameter entirely, and just pass ViewData["SearchData"] as my route value, my link is generated how I'd like (ie each member of PropertySearchData is passed along as a query string through the model binding feature. I'm guessing this is because model binding can only work correctly when you've specified a single type?

I can see several reasons as to why this doesn't work; what I am having trouble with is working out the 'nice' way to do what I'm trying to do. I know that I must be lacking a vital piece of understanding here, so it would be greatly appreciated if I can get some pointers on how to approach this.

Note that I really want to stick with HTTP GET (seeing as this is a search results page).

Thanks!

+2  A: 

Since data or ViewData["SearchData"] is in instance of PropertySearchData I'm guessing that Html.ActionLink is calling ToString() on it and not giving the result you would expect.

Jordan S. Jones
+1  A: 

The problem is the helper method is just trying it's best to generate something from what you've given it and that's an object with two properties: data and page.

To get the page number in you could make use of a route value dictionary (which is probably what's done under the hood anyway) and make use of the override that accepts an IDictionary:-

//In some HtmlHelper extension method or something 
var searchCriteria = new RouteValueDictionary(ViewData["searchData"]);
searchCriteria.Add("page", 1);

return Html.ActionLink("First", "Results", searchCriteria)
sighohwell
Ah, that's nice and tidy, thanks!
CapBBeard
+1  A: 

Creating an HtmlHelper extension method would not be the best way to solve this. It won't add general functionality, only more (visual) clutter...

The routeValues overload of Html.ActionLink expects an object or RouteValueCollection (IDictionary). You are now using the object overload (since the new {} constructor is an anonymous object).

You could use the following to create the correct routeValues parameter:

new RouteValueCollection(ViewData["SearchData"]) { { "page", 1 } }

This initializes a new RouteValueCollection with the current search data and then adds the 'page' key with the new value (overwrites if it exists in search data).

Ronald