Search code examples
c#asp.net-mvcasp.net-mvc-3razorwebgrid

Webgrid: Maintain Filter after Sorting


I have set up a webgrid and it seems to work fine, allowing me to sort and page. I have added a filter option which also works well however if I filter and then sort the results, the filter is lost and all records are displayed.

Here is my Razor view code:

@using (Ajax.BeginForm(new AjaxOptions { HttpMethod = "Get", InsertionMode = InsertionMode.Replace, UpdateTargetId = "myGrid" }))
{

@Html.ValidationSummary(true)
<fieldset>
    <legend>Document Search</legend>

    <div class="editor-label">
        @Html.Label("Enter a Document code:")
    </div>
    <div class="editor-field">
        @Html.Editor("search")
    </div>

    <p>
        <input type="submit" value="Search" />
    </p>
</fieldset>
}

@{
    WebGrid grid = new WebGrid(null, rowsPerPage: 10, canPage: true, canSort: true, ajaxUpdateContainerId: "myGrid");
    grid.Bind(Model, autoSortAndPage: true);
}

<div id="myGrid">

    @grid.GetHtml(mode: WebGridPagerModes.All, firstText: "First Page", nextText: "Next", previousText: "Previous", lastText: "Last Page", numericLinksCount: 10,
            columns: grid.Columns(
                grid.Column("DocumentID", "Document Code", canSort: true),
                grid.Column("Title", "Document Title", canSort: true)
        )
    )

</div>

And here is my action:

public ActionResult Index(string search)
    {
        List<DocumentIndexViewModel> viewModel = Mapper.Map<List<DocumentIndexViewModel>>(DocumentService.GetDocumentsBySearch(search));
        if (Request.IsAjaxRequest())
            return PartialView("_IndexGrid", viewModel);
        else
            return View(viewModel);
    }

How do I maintain the filter when I sort the displayed records? It seems like I need to append the search string onto the sort links somehow but am not sure how to proceed.


Solution

  • Since you are using GET for the filter this should preserve it. I am unable to reproduce the problem. Here's my full working test case.

    Model:

    public class CityViewModel
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }
    

    Controller:

    public class HomeController : Controller
    {
        public ActionResult Index(string search)
        {
            using (var client = new WebClient())
            {
                var query = HttpUtility.ParseQueryString(string.Empty);
                query["q"] = search;
                var json = client.DownloadString("http://gd.geobytes.com/AutoCompleteCity?" + query.ToString());
                var serializer = new JavaScriptSerializer();
                var viewModel = serializer
                    .Deserialize<string[]>(json)
                    .Select((x, index) => new CityViewModel
                    {
                        Id = index,
                        Name = x
                    })
                    .Where(x => x.Name.StartsWith(search ?? string.Empty, StringComparison.OrdinalIgnoreCase))
                    .ToList();
    
                if (Request.IsAjaxRequest())
                {
                    return PartialView("_IndexGrid", viewModel);
                }
                else
                {
                    return View(viewModel);
                }
            }
        }
    }
    

    Main view (~/Views/Home/Index.cshtml):

    @model IEnumerable<CityViewModel>
    
    <script src="@Url.Content("~/Scripts/jquery.unobtrusive-ajax.js")" type="text/javascript"></script>
    <script type="text/javascript">
        $.ajaxSetup({
            cache: false
        });
    </script>
    
    @using (Ajax.BeginForm(new AjaxOptions { HttpMethod = "GET", InsertionMode = InsertionMode.Replace, UpdateTargetId = "gridPartial" }))
    {
        @Html.ValidationSummary(true)
        <fieldset>
            <legend>Document Search</legend>
    
            <div class="editor-label">
                @Html.Label("Enter a Document code:")
            </div>
            <div class="editor-field">
                @Html.Editor("search")
            </div>
    
            <p>
                <input type="submit" value="Search" />
            </p>
        </fieldset>
    }
    
    <div id="gridPartial">
        @Html.Partial("_IndexGrid")
    </div>
    

    ~/Views/Home/_IndexGrid.cshtml partial:

    @model IEnumerable<CityViewModel>
    
    @{
        WebGrid grid = new WebGrid(null, rowsPerPage: 10, canPage: true, canSort: true, ajaxUpdateContainerId: "myGrid");
        grid.Bind(Model, autoSortAndPage: true);
    }
    
    <div id="myGrid">
        @grid.GetHtml(mode: WebGridPagerModes.All, firstText: "First Page", nextText: "Next", previousText: "Previous", lastText: "Last Page", numericLinksCount: 10,
            columns: grid.Columns(
                grid.Column("Id", "City Id", canSort: true),
                grid.Column("Name", "City Name", canSort: true)
            )
        )
    </div>
    

    Sorting and pagination preserves the search filter that was entered because it was in the query string.