ASP .NET Core – Iniciando com ASP .NET Core MVC e Entity Framework Core no VS 2017 – Parte 07
No seguinte artigo, o autor apresenta a sétima parte de uma série focada em ASP.NET e Entity no Visual Studio.
Neste artigo, vamos iniciar a criação de uma aplicação ASP .NET Core MVC usando o Entity Framework Core no Visual Studio 2017.
Estamos criando uma aplicação Web usando ASP.NET Core 1.1 MVC com Entity Framework Core 1.1 e Visual Studio 2017.
No artigo anterior, implementamos o filtro de dados adicionando uma caixa de pesquisa na página Index.
Continuaremos incrementando a página Index incluindo o recurso da paginação dos dados.
1 – Incluindo a paginação na página Index
Para adicionar o recurso da paginação para a página Index dos estudantes, vamos criar uma classe chamada PaginatedList que usa as instruções Skip e Take para filtrar dados no servidor em vez de sempre recuperar todas as linhas da tabela.
Em seguida, faremos alterações adicionais no método Index do controlador e depois vamos adicionar botões de paginação na respectiva view Index.
Selecione o projeto, no menu Tools clique em Add Class, informe o nome PaginatedList.cs e clique no botão Add.
A seguir, inclua o código abaixo nesta classe:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
namespace UniversidadeMacoratti
{
public class PaginatedList<T> : List<T>
{
public int PageIndex { get; private set; }
public int TotalPages { get; private set; }
public PaginatedList(List<T> items, int count, int pageIndex, int pageSize)
{
PageIndex = pageIndex;
TotalPages = (int)Math.Ceiling(count / (double)pageSize);
this.AddRange(items);
}
public bool HasPreviousPage
{
get
{
return (PageIndex > 1);
}
}
public bool HasNextPage
{
get
{
return (PageIndex < TotalPages);
}
}
public static async Task<PaginatedList<T>> CreateAsync(IQueryable<T> source, int pageIndex, int pageSize)
{
var count = await source.CountAsync();
var items = await source.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToListAsync();
return new PaginatedList<T>(items, count, pageIndex, pageSize);
}
}
}
O método CreateAsync neste código obtém o tamanho da página, número de página e aplica as instruções Skip e Take ao IQueryable. Quando ToListAsync for chamado no IQueryable, ele retornará uma lista contendo apenas a página solicitada. As propriedades HasPreviousPage e HasNextPage podem ser usadas para ativar ou desativar os botões de paginação Anterior e Próxima.
O método CreateAsync é usado em vez de um construtor para criar o objeto PaginatedList<T> porque construtores não podem executar código assíncrono.
2 – Incluindo o recurso da paginação no método Index do Controlador
Agora vamos incluir o recurso de paginação no controlador EstudantesController.
Abra o arquivo EstudantesController.cs e altere o método Index() conforme o código mostrado a seguir:
// GET: Estudantes
public async Task<IActionResult> Index(
string ordem,
string filtroAtual,
string filtro,
int? pagina)
{
ViewData["ordemAtual"] = ordem;
ViewData["NomeParm"] = String.IsNullOrEmpty(ordem) ? "nome_desc" : "";
ViewData["DataParm"] = ordem == "Data" ? "data_desc" : "Data";
if (filtro != null)
{
pagina = 1;
}
else
{
filtro = filtroAtual;
}
ViewData["filtroAtual"] = filtro;
var estudantes = from est in _context.Estudantes
select est;
if (!String.IsNullOrEmpty(filtro))
{
estudantes = estudantes.Where(est => est.SobreNome.Contains(filtro)
|| est.Nome.Contains(filtro));
}
switch (ordem)
{
case "nome_desc":
estudantes = estudantes.OrderByDescending(est => est.SobreNome);
break;
case "Data":
estudantes = estudantes.OrderBy(est => est.DataMatricula);
break;
case "data_desc":
estudantes = estudantes.OrderByDescending(est => est.DataMatricula);
break;
default:
estudantes = estudantes.OrderBy(est => est.SobreNome);
break;
}
int pageSize = 3;
return View(await PaginatedList<Estudante>.CreateAsync(estudantes.AsNoTracking(), pagina ?? 1, pageSize));
}
Esse código adiciona um parâmetro de número de página, um parâmetro de ordem de classificação atual e um parâmetro de filtro atual para a assinatura do método.
Na primeira vez que a página for exibida, ou se o usuário não clicar em um link de paginação ou classificação, todos os parâmetros serão nulos. Se um link de paginação for clicado, a variável pagina conterá o número da página a ser exibido.
O elemento ViewData chamado ordemAtual fornece a view com a ordem de classificação atual, pois isso deve ser incluído nos links de paginação para manter a ordem de classificação durante a paginação.
O elemento ViewData denominado filtroAtual, fornece a view com a string de filtro actual. Esse valor deve ser incluído nos links de paginação para manter as configurações de filtro durante a paginação, e deve ser restaurado para a caixa de texto quando a página é exibida novamente.
Se a seqüência de pesquisa for alterada durante a paginação, a página deve ser redefinida para 1, pois o novo filtro pode resultar em dados diferentes para exibição. A string de pesquisa é alterada quando um valor é inserido na caixa de texto e o botão Enviar é pressionado. Nesse caso, o parâmetro filtro não é nulo.
Ao final do método Index, o método PaginatedList.CreateAsync converte a consulta do estudante em uma única página de estudantes, em um tipo de coleção que ofereça suporte à paginação. Essa única página de alunos é então passada para a view.
O método PaginatedList.CreateAsync toma um número de página. Os dois pontos de interrogação representam o operador nulo-coalescente. O operador nulo-coalescente define um valor padrão para um tipo anulável; A expressão “página ?? 1” significa retornar o valor da página se ela tiver um valor, ou retornar 1 se a página for nula.
3 – Incluindo os links na view Index
Agora vamos definir o código abaixo na view Index da pasta Views/Estudantes:
@model PaginatedList<UniversidadeMacoratti.Models.Estudante>
@{
ViewData["Title"] = "Index";
}
<h2>Estudantes</h2>
<p>
<a asp-action="Create">Criar Novo Estudante</a>
</p>
<form asp-action="Index" method="get">
<div class="form-actions no-color">
<p>
Procurar por nome : <input type="text" name="filtro" value="@ViewData["filtroAtual"]" />
<input type="submit" value="Procurar" class="btn btn-default" /> |
<a asp-action="Index">Retornar para lista</a>
</p>
</div>
</form>
<table class="table">
<thead>
<tr>
<th>
<a asp-action="Index" asp-route-ordem="@ViewData["NomeParam"]" asp-route-filtroAtual="@ViewData["filtroAtual"]">Sobrenome</a>
</th>
<th>
Nome
</th>
<th>
<a asp-action="Index" asp-route-ordem="@ViewData["DataParm"]" asp-route-filtroAtual="@ViewData["filtroAtual"]">Data de Matrícula</a>
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.SobreNome)
</td>
<td>
@Html.DisplayFor(modelItem => item.Nome)
</td>
<td>
@Html.DisplayFor(modelItem => item.DataMatricula)
</td>
<td>
<a asp-action="Edit" asp-route-id="@item.EstudanteID">Editar</a> |
<a asp-action="Details" asp-route-id="@item.EstudanteID">Detalhes</a> |
<a asp-action="Delete" asp-route-id="@item.EstudanteID">Deletar</a>
</td>
</tr>
}
</tbody>
</table>
@{
var prevDisabled = !Model.HasPreviousPage ? "disabled" : "";
var nextDisabled = !Model.HasNextPage ? "disabled" : "";
}
<a asp-action="Index"
asp-route-ordem="@ViewData["ordemAtual"]"
asp-route-pagina="@(Model.PageIndex - 1)"
asp-route-filtroAtual="@ViewData["filtroAtual"]"
class="btn btn-default @prevDisabled">
Anterior
</a>
<a asp-action="Index"
asp-route-ordem="@ViewData["ordemAtual"]"
asp-route-pagina="@(Model.PageIndex + 1)"
asp-route-filtroAtual="@ViewData["filtroAtual"]"
class="btn btn-default @nextDisabled">
Próximo
</a>
Nota: Novamente estamos usando as Tag Helpers: <form> , asp-action e asp-route.
Os links de cabeçalho de coluna usam a string de consulta para passar a string de pesquisa atual para o controlador, para que o usuário possa classificar os resultados do filtro:
<a asp-action="Index" asp-route-ordem="@ViewData["DataParm"]" asp-route-filtroAtual="@ViewData["filtroAtual"]">Data de Matrícula</a>
Os botões de paginação são exibidos usando tag-helpers:
<a asp-action="Index"
asp-route-ordem="@ViewData["ordemAtual"]"
asp-route-pagina="@(Model.PageIndex - 1)"
asp-route-filtroAtual="@ViewData["filtroAtual"]"
class="btn btn-default @prevDisabled">
Anterior
</a>
<a asp-action="Index"
asp-route-ordem="@ViewData["ordemAtual"]"
asp-route-pagina="@(Model.PageIndex + 1)"
asp-route-filtroAtual="@ViewData["filtroAtual"]"
class="btn btn-default @nextDisabled">
Próximo
</a>
Execute o projeto e abra a página dos estudantes:

Clique nos links de paginação em ordens de classificação diferentes para garantir que a paginação esta funcionando. Em seguida, digite uma string de caracteres de pesquisa e tente a paginação novamente para verificar se a paginação também funciona corretamente com classificação e filtragem.
Na próxima parte do artigo, criaremos uma página para exibir estatísticas sobre os estudantes.
Pegue o projeto funcionando aqui: UniversidadeMacoratti.zip








