ASP.NET MVC Paging - Passing Complex Types Back to Controller?
I am currently working on a fairly simple MVC application that allows the user to enter some search data, get a list of results, then view each item, etc. This all happens quite nicely, however now I am trying to implement paging but with some problems.
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 am building the results table from the IEnumerable collection passed to my view. Also, I used ViewData to store search parameters so that I can pass them when the user requests another page.
For example, to go to the first page, I would like to use something like this:
Html.ActionLink("First", "Results", new { data = ViewData["SearchData"], page = 1 })
However, when this link is created, my link is along the lines
/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 as I would like (ie each PropertySearchData member is passed as a query string through the model binding function. I'm guessing this is because model binding can only work correctly if you have specified one type?
I see several reasons why this doesn't work; I'm having trouble devising a "good" way of doing what I'm trying to do. I know I am missing a vital understanding here, so it would be very helpful if I can figure out how to approach this.
Note that I really want to stick with HTTP GET (seeing as this is a search results page).
Thank!
a source to share
The problem is that the helper method is just trying to create something from what you gave it, and that an object with two properties: data and a page.
To get the page number, you can use a dictionary of route values ββ(which is probably done under the hood after all), and use an override that IDictionary takes: -
//In some HtmlHelper extension method or something
var searchCriteria = new RouteValueDictionary(ViewData["searchData"]);
searchCriteria.Add("page", 1);
return Html.ActionLink("First", "Results", searchCriteria)
a source to share
Making an extension method HtmlHelper would not be the best way to solve this problem. It won't add general functionality, just more (visual) clutter ...
The routeValues ββoverload from Html.ActionLink expects an Object or RouteValueCollection (IDictionary). You are now using object overloading (since the new constructor {} is an anonymous object).
You can 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 a new value (overwrites if it exists in the search data).
a source to share