c# asp.net-mvc entity-framework asp.net-mvc-5 pagedlist

c# - ¿Cómo aplico el filtro al paginar en Asp.net MVC y entidad Framework?



asp.net-mvc entity-framework (3)

Creo que una mejor manera debería ser volver a ver los filtros en ViewBag . Puedes hacer algo como a continuación:

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

Pero tenga en cuenta para probar ViewBag.Status para el valor nulo. Si tiene un valor, colóquelo en la lista de parámetros de ruta; de lo contrario, establezca un ActionLink predeterminado.

Luego, dentro de la acción POST, espera un int anulable como a continuación:

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); }

Tengo una aplicación web que está escrita usando el framework ASP.NET MVC. En mi Homecontroller tengo una acción llamada Index que responde a una solicitud Get . En esta acción, creo páginas usando la biblioteca IPagedList para dividir los registros en varias páginas. Mi Index@HttpGet parece a esto

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); } }

También tengo una acción llamada Index que responde a la solicitud de Post que aplica algunos filtros. Entonces, en la solicitud de Post , hago algo como esto

[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); }

Esto también funciona bien a menos que el usuario haya cambiado la página, entonces los filtros son resto.

Así es como se ve mi clase de presentación

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; } }

¿Cómo puedo permitir que los usuarios usen las páginas mientras mantienen los filtros?

Aquí está mi VM de filtros

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

La vista se ve así

@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 }))


Dos formas de hacer esto.

La forma rápida: las cookies.

Simplemente configure una cookie para las opciones de filtro. En las acciones donde se requiere filtrado, todo lo que necesita hacer es leer las cookies y filtrar en consecuencia.
No me gustan las cookies y las sesiones, y las evitaría. Pero a veces puede ser lo que necesitas.

Usar parámetros GET

En su ejemplo, ha utilizado POST para filtrar. Cada vez que hace clic en un enlace, se activa una solicitud GET , no una POST . Entonces el filtrado no sucede. La parte difícil es asegurarse de que los parámetros GET estén establecidos cada vez. Podría crear una extensión personalizada similar a Html.Action() para comenzar. Si va a verificar las opciones de filtro en varias acciones, considere usar un Filter acción.


Su formulario debe volver a publicarse en el método GET, y ese método debe incluir parámetros para sus propiedades de filtro. El código de PagedListPager en la vista también debe incluir esas propiedades de filtro para que se conserven cuando navega a la página siguiente / anterior. Tenga en cuenta que el método POST Index() no se utiliza y puede eliminarse.

Hacer que su modelo contenga un objeto complejo para las propiedades del filtro y una complejidad adicional al vincular, así que comience cambiando su modelo a

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; } }

Luego cambie el método Index() a

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 ); }

y cambia la vista a

// 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