如何在 Asp.net MVC 和实体框架中分页时应用过滤器? [英] How to I apply filter while paginating in Asp.net MVC and entity Framework?

查看:16
本文介绍了如何在 Asp.net MVC 和实体框架中分页时应用过滤器?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个使用 ASP.NET MVC 框架编写的 Web 应用程序.在我的 Homecontroller 中,我有一个名为 Index 的操作,它响应 Get 请求.在此操作中,我使用 IPagedList 库创建页面以将记录分成多个页面.我的 Index@HttpGet 看起来像这样

public ActionResult Index(int?id){使用(无功连接=新的上下文()){int pageNumber = (id ?? 1);var 演示者 = 新演示者{演示者 = 页码,任务 = connection.Tasks.ToPagedList(pageNumber, 30),Form = new TasksFiltersViewModel()}返回视图(演示者);}}

我还有一个名为 Index 的操作,用于响应应用一些过滤器的 Post 请求.所以在 Post 请求中我做这样的事情

[HttpPost][验证AntiForgeryToken]公共 ActionResult 索引(Presenter 模型){int pageNumber = (id ?? 1);如果(模型状态.IsValid){使用(无功连接=新的上下文()){模型.任务 = 连接.任务.Where(task => task.Status == 5).ToPagedList(pageNumber, 30);}}返回视图(模型);}

这也可以正常工作,除非用户更改了页面,然后过滤器才会休息.

这是我的演示课的样子

公共类Presenter{公共 IPagedList任务{得到;放;}公共 TasksFiltersViewModel 表单 { get;放;}公共 int PageNumber { 获取;放;}公共 IEnumerable状态 { 获取;放;}}

如何在保留过滤器的同时允许用户使用页面?

这是我的过滤器虚拟机

公共类TasksFiltersViewModel{公共 int 状态 { 获取;放;}}

视图看起来像这样

@using (Html.BeginForm("Index", "Tasks", FormMethod.Post, new { @class = "form-horizo​​ntal" })){@Html.AntiForgeryToken()<div class="form-group">@Html.LabelFor(m => m.Form.Status, new { @class = "control-label col-sm-3" })<div class="col-sm-9">@Html.DropDownListFor(m => m.Form.Status, Model.Statuses, new { @class = "form-control" })@Html.ValidationMessageFor(m => m.Form.Status, "", new { @class = "text-danger" })

<div class="row"><div class="col-sm-9 col-md-push-3"><div><button type="submit" class="btn btn-default">过滤器</button>

}foreach(Model.Tasks 中的 var 任务){<tr><td>@task.Name</td><td>@task.Type</td><td>@Html.ActionLink("Edit", "Details", "Task", new { @id = task.Id }, new { @class = "btn btn-primary btn-sm" })</td></tr>}@Html.PagedListPager(Model.Tasks, id => Url.Action("Index", new { id }))

解决方案

您的表单需要回发到 GET 方法,并且该方法需要包含过滤器属性的参数.您在视图中的 PagedListPager 代码也需要包含这些过滤器属性,以便在您导航到下一页/上一页时保留它们.请注意,Index() POST 方法未使用,可以删除.

让你的模型包含一个复杂的对象到过滤器属性和绑定时额外的复杂性,所以首先将你的模型更改为

公共类Presenter{公共 IPagedList任务{得到;放;}公众号?状态 { 得到;放;}//注意可以为空...//添加 TasksFiltersViewModel 的任何其他属性公共 int PageNumber { 获取;放;}公共 IEnumerable状态 { 获取;放;}}

然后将Index()方法改为

public ActionResult Index(int? id, int? status)//添加任何其他过滤参数{int pageNumber = (id ?? 1);var 任务 = db.Tasks;//IQueryable如果(状态.HasValue){任务 = tasks.Where(x => x.Status == status.Value)}如果(otherParametersHaveValue){任务 = tasks.Where(....);}演示者模型 = 新演示者(){页码 = id ??1、状态 = 状态,....//从参数中设置任何其他过滤器属性状态 = 新的 SelectList(...),任务 = tasks.ToPagedList(pageNumber, 30)};返回视图(模型);}

并将视图更改为

//使表单成为 GET@using (Html.BeginForm("Index", "Tasks", FormMethod.Get, new { @class = "form-horizo​​ntal" })){....//根据修改后的模型属性修改表达式@Html.DropDownListFor(m => m.Status, Model.Statuses, ...)}....//将过滤器参数添加到 url 以保留它们@Html.PagedListPager(Model.Tasks, id => Url.Action("Index", new { id, status = Model.Status }))//根据需要添加其他过滤器属性

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 request. In this action, I create pages using IPagedList library to break the records into multiple pages. My Index@HttpGet looks something like this

public ActionResult Index(int? id)
{
    using(var connection = new Context())
    {
        int pageNumber = (id ?? 1);
        var presenter = new Presenter
        {
            Presenter = pageNumber,
            Tasks = connection.Tasks.ToPagedList(pageNumber, 30),
            Form = new TasksFiltersViewModel()
        }

        return View(presenter);
    }
}

I also have an action called Index that respond to the Post request which apply some filters. So in the Post request I do something like this

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Index(Presenter model)
{
    int pageNumber = (id ?? 1);
    if (ModelState.IsValid)
    {
        using(var connection = new Context())
        {
            model.Tasks = connection.Tasks
                                    .Where(task => task.Status == 5)
                                    .ToPagedList(pageNumber, 30);
        }
    }

    return View(model);
}

This also work fine unless the user changed the page then the filters are rest.

Here is how my presentation class looks like

public class Presenter
{
    public IPagedList<Task> Tasks { get; set; }
    public TasksFiltersViewModel Form { get; set; }
    public int PageNumber { get; set; }
    public IEnumerable<SelectListItem> Statuses { get; set; }
}

How can I allow the users to use the pages while keeping the filters?

Here is my filters VM

public class TasksFiltersViewModel
{
    public int Status { get; set; }
}

The view looks like this

@using (Html.BeginForm("Index", "Tasks", FormMethod.Post, new { @class = "form-horizontal" }))
{
    @Html.AntiForgeryToken()

    <div class="form-group">
        @Html.LabelFor(m => m.Form.Status, new { @class = "control-label col-sm-3" })
        <div class="col-sm-9">
            @Html.DropDownListFor(m => m.Form.Status, Model.Statuses, new { @class = "form-control" })
            @Html.ValidationMessageFor(m => m.Form.Status, "", new { @class = "text-danger" })
        </div>

    </div>

    <div class="row">
        <div class="col-sm-9 col-md-push-3">
            <div>
                <button type="submit" class="btn btn-default">Filter</button>
            </div>
        </div>
    </div>

}

foreach (var task in Model.Tasks)
{
    <tr>
        <td>@task.Name</td>
        <td>@task.Type</td>
        <td>@Html.ActionLink("Edit", "Details", "Task", new { @id = task.Id }, new { @class = "btn btn-primary btn-sm" })</td>
    </tr>
}


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

解决方案

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

这篇关于如何在 Asp.net MVC 和实体框架中分页时应用过滤器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
C#/.NET最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆