How to I apply filter while paginating in Asp.net MVC and entity Framework?

前端 未结 3 774
傲寒
傲寒 2020-11-28 16:01

I have a web app that is written using ASP.NET MVC framework. In my Homecontroller I have an action called Index which responds to a Get

相关标签:
3条回答
  • 2020-11-28 16:34

    I think a better way should be passing back to the view the filters in ViewBag. You can make something like below:

    @Html.PagedListPager(
    Model.Tasks, id => 
    Url.Action("Index", new { id, 
    Status = ViewBag.Status , AnotherFilterValue = ViewBag.AnotherFilterValue, ...  }))
    

    But keep in mind to test ViewBag.Status for null value. If it does have a value put it in the route parameter list else set a default ActionLink.

    Then inside the POST action you expect a nullable int like below:

    public ActionResult Index(int? id, int? status, ...)
    {
        int pageNumber = (id ?? 1);
        if (ModelState.IsValid)
        {
    
        using(var connection = new Context())
        {
            if(status != null)
            {
              ViewBag.Status = status.value;
              model.Tasks = connection.Tasks
                                    .Where(task => task.Status == status.value)
                                    .ToPagedList(pageNumber, 30);
            }
            else
            {
               model.Tasks = connection.Tasks
                                      .ToPagedList(pageNumber, 30);
            }
          }
        }
    
       return View(model);
    }
    
    0 讨论(0)
  • 2020-11-28 16:41

    Your form needs to post back to the GET method, and that method needs to include parameters for your filter properties. Your PagedListPager code in the view also need to include those filter properties so they are retained when you navigate to the next/previous page. Note that the Index() POST method is not used and can be deleted.

    Having your model contain a complex object to the filter properties and extra complexity when binding, so start by changing your model to

    public class Presenter
    {
        public IPagedList<Task> Tasks { get; set; }
        public int? Status { get; set; } // note nullable
        ... // add any other properties of TasksFiltersViewModel 
        public int PageNumber { get; set; }
        public IEnumerable<SelectListItem> Statuses { get; set; }
    }
    

    Then change the Index() method to

    public ActionResult Index(int? id, int? status) // add any other parameters your filtering on
    {
        int pageNumber = (id ?? 1);
        var tasks = db.Tasks; // IQueryable<Task>
        if (status.HasValue)
        {
            tasks = tasks.Where(x => x.Status == status.Value)
        }
        if (otherParametersHaveValue)
        {
            tasks = tasks.Where(....);
        }
        Presenter model = new Presenter()
        {
            PageNumber = id ?? 1,
            Status = status,
            .... // set any other filter properties from the parameters
            Statuses = new SelectList(...),
            Tasks = tasks.ToPagedList(pageNumber, 30)
        };
        return View(model );
    }
    

    and change the view to

    // Make the form a GET
    @using (Html.BeginForm("Index", "Tasks", FormMethod.Get, new { @class = "form-horizontal" }))
    {
        ....
        // Modify expression based on revised model properties
        @Html.DropDownListFor(m => m.Status, Model.Statuses, ...)
    }
    ....
    // Add filter parameters to url so they are retained
    @Html.PagedListPager(Model.Tasks, id => Url.Action("Index", new { id, status = Model.Status })) // add other filter properties as required
    
    0 讨论(0)
  • 2020-11-28 16:55

    Two ways to do this.

    The quick way: Cookies.

    Just set a cookie for the filter options. On the actions where filtering is required, all you need to do is read the cookies and filter accordingly.
    I dislike cookies and sessions, and would avoid them. But sometimes it could turn out to be what you need.

    Use GET parameters

    In your example you've used POST to filter. Each time you click on a link, it fires a GET request, not a POST. So the filtering doesn't happen. The tricky part is making sure the GET parameters are set each time. Could create a custom extension similar to Html.Action() to start with. If you'll be checking the filter options in multiple actions, consider using an action Filter.

    0 讨论(0)
提交回复
热议问题