.NET

1 nov, 2017

ASP .NET Core – Iniciando com ASP .NET Core MVC e Entity Framework Core no VS 2017 – Parte 06

Publicidade

Neste artigo vou continuar 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 a classificação por colunas na página Index dos estudantes.

Neste artigo vamos continuar incrementando a página Index incluindo uma caixa de pesquisa na página para filtrar dados por nome e/ou sobrenome.

1 – Filtrando dados : Incluindo um filtro no controlador

Vamos agora adicionar um filtro na página Index dos estudantes. Para isso, vamos ter que adicionar uma caixa de texto e um botão de envio na view Index e realizar alterações correspondentes no método Action Index do controlador EstudantesController.

A caixa de texto permitirá que o usuário digite uma seqüência de caracteres para procurar nos campos nome e sobrenome.

Vamos começar implementando a funcionalidade para realizar um filtro de dados no método Index do controlador Estudantes.

Abra o arquivo EstudantesController.cs e altere o método Index conforme mostrado a seguir, incluindo as linhas destacadas em azul no código:

  // GET: Estudantes
        public async Task<IActionResult> Index(string ordem, string filtro)
        {
            ViewData["NomeParm"] = String.IsNullOrEmpty(ordem) ? "nome_desc" : "";
            ViewData["DataParm"] = ordem == "Data" ? "data_desc" : "Data";
            ViewData["filtro"] = filtro;
            var estudantes = from est in _context.Estudantes
                             select est;
            if (!String.IsNullOrEmpty(filtro))
            {
                estudantes = estudantes.Where(s => s.SobreNome.Contains(filtro)
                                       || s.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;
            }

            return View(await estudantes.AsNoTracking().ToListAsync());
        }

Neste código, incluímos um novo parâmetro chamado filtro do tipo string no método Index. O valor de filtro será uma cadeia de caracteres e será recebido de uma caixa de texto que iremos adicionar na view Index.

Além disso, incluímos na instrução LINQ uma cláusula Where que seleciona apenas os estudantes com nome e sobrenome que contém a string informada em filtro. Essa instrução somente será executada se houver um filtro informado.

Neste código, estamos usando a cláusula Where em um objeto IQueryable, e o filtro será processado no servidor. Em alguns cenários podemos usar o Where como um método de extensão em uma coleção na memória. Por exemplo, suponha que você altere a referência _context.Estudantes para que em vez de usar um DBSet do EF, ele faça referência a um método de um repositório que retorna uma coleção IEnumerable. O resultado seria normalmente o mesmo, mas em alguns casos pode ser diferente.

Por exemplo, a implementação do .NET Framework para o método Contains realiza uma comparação sensível à maiúsculas e minúsculas por predefinição, mas no SQL Server isto é determinado pela definição de collation da instância do SQL Server.

Essa configuração padrão é insensível a maiúsculas e minúsculas. Você pode chamar o método ToUpper para tornar o teste explicitamente insensível a maiúsculas e minúsculas assim: Where (est => est.Sobrenome.ToUpper().Contains(filtro.ToUpper()).

Isso garantiria que os resultados permaneçam os mesmos se você alterar o código mais tarde para usar um repositório que retorna uma coleção IEnumerable em vez de um objeto IQueryable (quando você chama o método Contains em uma coleção IEnumerable, você obtém a implementação do .NET Framework, e, quando você chama o método em um objeto IQueryable, você obtém a implementação do provedor do banco de dados).

No entanto, há uma penalidade de desempenho para esta solução. O código ToUpper colocaria uma função na cláusula WHERE da instrução SELECT TSQL. Isso impediria o otimizador de usar um índice. Dado que o SQL é principalmente instalado como insensível a maiúsculas e minúsculas, é melhor evitar o código ToUpper até migrar para um armazenamento de dados sensível a maiúsculas e minúsculas.

2 – Filtrando dados: Adicionando uma caixa de Pesquisa

Vamos agora adicionar uma caixa de pesquisa na view Index da pasta Views/Estudantes para que o usuário possa informar a cadeia de caracteres usada para filtrar os dados.

Abra o arquivo Index.cshtml e inclua o código destacado em azul abaixo, antes da tag Table para criar um título, uma caixa de texto e um botão Procurar:

@model IEnumerable<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["filtro"]" />
            <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["NomeParm"]">@Html.DisplayNameFor(model => model.SobreNome)</a>
                </th>
                <th>
                    @Html.DisplayNameFor(model => model.Nome)
                </th>
                <th>
                    <a asp-action="Index" asp-route-ordem="@ViewData["DataParm"]">@Html.DisplayNameFor(model => model.DataMatricula)</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>

Nota: Novamente estamos usando as Tag Helpers <form> e asp-action.

Neste código usamos a informação na propriedade ViewData para definir os hiperlinks com os valores apropriadas da string de consulta.

Este código usa a tag helper <form> para adicionar a caixa de texto de pesquisa e o botão. Por padrão, a tag helper <form> envia dados de formulário com um POST, o que significa que os parâmetros são passados no corpo da mensagem HTTP, e não na URL como uma string de consulta.

Quando você especifica HTTP GET, os dados do formulário são passados na URL como strings de consulta, o que permite aos usuários marcar o URL. As diretrizes do W3C recomendam que você use GET quando a ação não resultar em uma atualização.

Execute o projeto, abra a página dos estudantes, e a seguir informe um nome para busca. O resultado obtido pode ser visto na figura abaixo:

Na próxima parte do artigo vamos incluir o recurso de paginação na página Index.