Asp.net Mvc3 webgrid and paging

adt picture adt · Jun 14, 2011 · Viewed 28.5k times · Source

I am trying to learn Asp.net mvc. I know its different from forms and i need to change my way of thinking probably. My problem is about webgrid . When i add webgrid to my page and hit search button with Post it renders table with pager and so on. But links on the pager is not posting form they are just links and i lost all my form's data.

Controller has two index methods one is for get and other is for post. For get i do nothing, I just create new viewmodel in this case Search class and set it to view. For my post method i grab my view model do search and set filled viewmodel to view.

problem : webgrid renders pager as links so it will enter to the Index for get but since it is not a post request i dont have any form fields filled and my search will not provide the very same result set.

Maybe example code can explain it better.

View:

<form action="" method="post">

Esas no : @Html.TextBoxFor(x=>x.Name)
Yil : @Html.TextBoxFor(x=>x.Year)

<input type="submit" value="Search" />

<hr />
@ViewBag.Message
<hr />

@{ var grid = new WebGrid(Model.Results,rowsPerPage:5);}

@grid.GetHtml(tableStyle:"table",htmlAttributes:new {id="tbl"} )

</form>

Here is My Controller: Search occures in Index Post method and it has just my viewmodel class.

    private ISearchContext _sc;

    public  MyController(ISearchContext sc)
    {
        _dc = dc;
    }

    //
    // GET: /Dava/

    public ActionResult Index()
    {
        var search = new Search();
        ViewBag.Message = "";
        return View(search);
    }

    [HttpPost]
    public ActionResult Index(Search search)
    {

        Search sres = _dc.SearchFromRepository(search);
        ViewBag.Message = String.Format("Count:{0} ",sres.Results.Count);
        return View(sres);
    }

Search model Class is like:

public class Search
{
    public int Year { get; set; }
    public string Name { get; set; }


    public IList<Item> Results { get; set; }

    public Search()
    {
        Results = new List<Item>();
    }
}

Answer

Darin Dimitrov picture Darin Dimitrov · Jun 14, 2011

One way to solve this issue is to use javascript and subscribe for the click event of any of the pager links and then fetch the value of the desired page, inject it into a hidden field on the form and submit the form to the server so that the other two values are also sent.

So start by adding a Page nullable integer property on your Search view model and a corresponding hidden field into the form which will contain the selected page number:

@Html.HiddenFor(x => x.Page, new { id = "page" })

Then all you need is a small javascript snippet into the page to subscribe for the .click event of the pager links:

$(function () {
    $('tfoot a').click(function () {
        // when the user clicks on any of the pager links
        // try to extract the page number from the link and
        // set the value of the hidden field
        var page = this.href.match(/page=([0-9])+/)[1];
        $('#page').val(page);

        // submit the form so that the POST action is invoked
        // passing along the search criteria (Name and Year) along
        // with the page hidden field value to the Index action
        $('form').submit();

        // cancel the default action of the link which is to simply redirect
        // to the Index action using a GET verb.
        return false;
    });
});