PagedList loses search filter on second page
Asked Answered
G

4

18

I'm implementing a simple paged list Index using the example at http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/sorting-filtering-and-paging-with-the-entity-framework-in-an-asp-net-mvc-application

My problem is that the search string is 'lost' when I page to the second page, so instead of a filtered set of results, I'm shown all the records.

My index.cshtml:

@using (Html.BeginForm("Index", "", FormMethod.Get))
{
    <p>
        @Html.TextBox("searchString", ViewBag.currentFilter as string, new { @placeholder = "Search by title or author" })
        <input type="submit" value="Search" />
    </p>
}

@if (Model.PageCount > 1)
{ 
    @Html.PagedListPager( Model, page => Url.Action("Index", new { page }) )
}

My controller:

public ViewResult Index(string sortOrder, string currentFilter, string searchString, int? page)
    {
        ViewBag.TitleSortParm = sortOrder == "Title" ? "Title desc" : "Title";
        ViewBag.AuthorSortParm = sortOrder == "Author" ? "Author desc" : "Author";
        ViewBag.DateSortParm = sortOrder == "Date" ? "Date desc" : "Date";

        if (searchString != null)
        {
            page = 1;
        }
        else
        {
            searchString = currentFilter;

        }

        ViewBag.currentFilter = searchString;

        var Articles = from a in db.Articles
                       select a;
        if (!String.IsNullOrEmpty(searchString))
        {
            //page = 1;
            Insights = Articles.Where(s => s.Title.ToUpper().Contains(searchString.ToUpper())
                               || s.Author.ToUpper().Contains(searchString.ToUpper()));
        }

        switch (sortOrder)
        {
            case "Author":
                Insights = Articles.OrderBy(s => s.Author);
                break;
            case "Author desc":
                Insights = Articles.OrderByDescending(s => s.Author);
                break;
            case "Title":
                Insights = Articles.OrderBy(s => s.Title);
                break;
            case "Title desc":
                Insights = Articles.OrderByDescending(s => s.Title);
                break;
            case "Date":
                Insights = Articles.OrderBy(s => s.DatePublished);
                break;
            default:
                Insights = Articles.OrderByDescending(s => s.DatePublished);
                break;
        }
        int pageSize = 3;
        int pageNumber = (page ?? 1);
        return View(Articles.ToPagedList(pageNumber, pageSize));

    }

When I go to Page 2 as an example, all my variables, sortOrder, currentFilter and searchString are all null.

Robbie

Gook answered 10/9, 2013 at 14:11 Comment(4)
I dont see code to set ViewBag.CurrentSort in the controller action. Try adding it: ViewBag.CurrentSort = sortOrder;Unction
Does the value of searchString get posted back to the textbox? If not, then you need to make sure you pass it back to the view after a search.Wailoo
It does, but only for the first post, it doesn't seem to get posted back when I go to the next page.Gook
What does your pager look like in your CSHTML?Midrib
M
23

The problem is your PagedList entry doesn't include your sort order nor your current filter.

In addition to adding ViewBag.CurrentSort as suggested by Vasanth, you also need to change your PagedListPager to:

@Html.PagedListPager( Model, page => Url.Action("Index", new { page, currentFilter=ViewBag.CurrentFilter, sortOrder = ViewBag.sortOrder}) )
Midrib answered 11/9, 2013 at 10:56 Comment(0)
W
2

Hello I figured this out, Use a Tempdata to hold the search parameters. When the search method is called with some values, store the values in a tempdata. When the page list calls the method for page 2, collect the Search parameters from the TempData.

See this:

            if (SearchParameter != null)
            {
                TempData["HoldSearch"] = SearchParameter;
                TempData.Keep();
            }
            else
            {
                SearchParameter  = (CastBacktoType)TempData["HoldSearch"];
                TempData.Keep();
            }

Have tried this, it works well

Winton answered 8/11, 2016 at 14:43 Comment(0)
T
2

If you have a complex search/filtering section with more than one field, you might need to use something like :

<div class="pagedList">
   @Html.PagedListPager(Model, page => Url.Action("Index", new { 
     page, sortOrder = ViewBag.CurrentSort,
     currentFilter = ViewBag.CurrentFilter,
     filter2= Request.QueryString["filter2"],
     filter3= Request.QueryString["filter3"],
     filter4= Request.QueryString["filter4"],
     filter5= Request.QueryString["filter5"] }))

   Page @(Model.PageCount < Model.PageNumber ? 0 : Model.PageNumber) of @Model.PageCount
</div>

This worked for me and now I can use complex filtering and view the results on multiple pages.

Thole answered 6/1, 2017 at 10:58 Comment(0)
U
0

To filter the data by applying multiple filters we can use ViewBag like this in View. For example if we want to apply filter for three fields(i.e EmpFirstName, EmpLastName, EmpLocation).

@Html.PagedListPager(Model, page => Url.Action("Index", new { 
                           page,
                           sortOrder = ViewBag.sortOrder,
                           currentFilter1 =ViewBag.CurrentFilterForEmpFirstName,
                           currentFilter2 =ViewBag.CurrentFilterForEmpLastName,
                           currentFilter3 =ViewBag.CurrentFilterForEmpLocation}))

Page @(Model.PageCount < Model.PageNumber ? 0 : Model.PageNumber) of @Model.PageCount

In controller i wroted code like this:

public ActionResult Index( int ?page, string currentFilter1, string currentFilter2, string currentFilter3,
 string searchEmpFirstName , string searchEmpLastName, string searchEmpLocation)

int pageSize = 10;
int pageNumber = (page??1);

var emp_master = db.Emp_Master.Include(l => l.Emp_Location);
   if (searchEmpFirstName != null || searchEmpLastName != null || searchEmpLocation != null)
   {
      page = 1;
   }
   else
   {
      searchEmpFirstName = currentFilter1;
      searchEmpLastName = currentFilter2;
      searchEmpLocation = currentFilter3;
   }

   ViewBag.CurrentFilterForEmpFirstName = searchEmpFirstName;
   ViewBag.CurrentFilterForEmpLastName = searchEmpLastName;
   ViewBag.CurrentFilterForEmpLocation = searchEmpLocation;

  if(!String.IsNullOrEmpty(searchEmpFirstName))
  {
      emp = emp.Where(s => s.ModelName == searchEmpFirstName)
  }
  if(!String.IsNullOrEmpty(searchEmpLastName))
  {
      emp = emp.Where(s => s.ModelName == searchEmpLastName)
  }
  if(!String.IsNullOrEmpty(searchEmpLocation))
  {
      emp = emp.Where(s => s.ModelName == searchEmpLocation)
  }
Unicef answered 19/4, 2021 at 17:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.