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!

+1


a source to share


3 answers


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)

      

+2


a source


Since data

or ViewData["SearchData"]

as an example PropertySearchData

, I am assuming that Html.ActionLink

is calling ToString()

on it and not giving the expected result.



+2


a source


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).

+1


a source







All Articles