Compartilhar via


Parte 6, adicionar a pesquisa ao Razor Pages do ASP.NET Core

Observação

Esta não é a versão mais recente deste artigo. Para informações sobre a versão vigente, confira a Versão do .NET 8 deste artigo.

Aviso

Esta versão do ASP.NET Core não tem mais suporte. Para obter mais informações, confira .NET e a Política de Suporte do .NET Core. Para informações sobre a versão vigente, confira a Versão do .NET 8 deste artigo.

Importante

Essas informações relacionam-se ao produto de pré-lançamento, que poderá ser substancialmente modificado antes do lançamento comercial. A Microsoft não oferece nenhuma garantia, explícita ou implícita, quanto às informações fornecidas aqui.

Para informações sobre a versão vigente, confira a Versão do .NET 8 deste artigo.

De Rick Anderson

Nas seções a seguir, a pesquisa de filmes por gênero ou nome é adicionada.

Adicione o código realçado a seguir a Pages/Movies/Index.cshtml.cs:

public class IndexModel : PageModel
{
    private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;

    public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
    {
        _context = context;
    }

    public IList<Movie> Movie { get;set; }  = default!;

    [BindProperty(SupportsGet = true)]
    public string? SearchString { get; set; }

    public SelectList? Genres { get; set; }

    [BindProperty(SupportsGet = true)]
    public string? MovieGenre { get; set; }

No código anterior:

  • SearchString: contém o texto que os usuários inserem na caixa de texto de pesquisa. SearchString tem o atributo [BindProperty]. [BindProperty] associa valores de formulário e cadeias de consulta ao mesmo nome da propriedade. [BindProperty(SupportsGet = true)] é necessário para a associação em solicitações HTTP GET.
  • Genres: contém a lista de gêneros. Genres permite que o usuário selecione um gênero na lista. SelectList exige using Microsoft.AspNetCore.Mvc.Rendering;
  • MovieGenre: contém o gênero específico selecionado pelo usuário. Por exemplo, "Faroreste".
  • Genres e MovieGenre são abordados mais adiante neste tutorial.

Aviso

Por motivos de segurança, você deve aceitar associar os dados da solicitação GET às propriedades do modelo de página. Verifique a entrada do usuário antes de mapeá-la para as propriedades. Aceitar a associação de GET é útil ao lidar com cenários que contam com a cadeia de caracteres de consulta ou com os valores de rota.

Para associar uma propriedade a solicitações GET, defina a propriedade SupportsGet do atributo [BindProperty] como true:

[BindProperty(SupportsGet = true)]

Para obter mais informações, confira ASP.NET Core Community Standup: Bind on GET discussion (YouTube).

Atualize o método OnGetAsync da página Movies/Index com o seguinte código:

public async Task OnGetAsync()
{
    var movies = from m in _context.Movie
                 select m;
    if (!string.IsNullOrEmpty(SearchString))
    {
        movies = movies.Where(s => s.Title.Contains(SearchString));
    }

    Movie = await movies.ToListAsync();
}

A primeira linha do método OnGetAsync cria uma consulta LINQ para selecionar os filmes:

var movies = from m in _context.Movie
             select m;

A consulta é definida somente neste ponto; ela não foi executada no banco de dados.

Se a propriedade SearchString não é null nem vazia, a consulta de filmes é modificada para filtrar a cadeia de caracteres de pesquisa:

if (!string.IsNullOrEmpty(SearchString))
{
    movies = movies.Where(s => s.Title.Contains(SearchString));
}

O código s => s.Title.Contains() é uma Expressão Lambda. Lambdas são usados em consultas LINQ baseadas em método como argumentos para métodos de operadores de consulta padrão, como o método Where ou Contains. As consultas LINQ não são executadas quando são definidas ou no momento em que são modificadas com uma chamada a um método, como Where, Contains ou OrderBy. Em vez disso, a execução da consulta é adiada. A avaliação de uma expressão é atrasada até que seu valor realizado seja iterado ou o método ToListAsync seja chamado. Consulte Execução de consulta para obter mais informações.

Observação

O método Contains é executado no banco de dados, não no código C#. A diferenciação de maiúsculas e minúsculas na consulta depende do banco de dados e da ordenação. No SQL Server, Contains é mapeado para SQL LIKE, que não diferencia maiúsculas de minúsculas. O SQLite com a ordenação padrão combina instruções que diferenciam ou não maiúsculas e minúsculas, a depender da consulta. Para obter informações sobre como instruir as consultas SQLite a não diferenciar maiúsculas de minúsculas, consulte os seguintes itens:

Navegue até a página Filmes e acrescente uma cadeia de consulta, como ?searchString=Ghost, à URL. Por exemplo, https://localhost:5001/Movies?searchString=Ghost. Os filmes filtrados são exibidos.

Exibição de índice

Se o modelo de rota a seguir for adicionado à página de Índice, a cadeia de caracteres de pesquisa poderá ser passada como um segmento de URL. Por exemplo, https://localhost:5001/Movies/Ghost.

@page "{searchString?}"

A restrição da rota anterior permite a pesquisa do título como dados de rota (um segmento de URL), em vez de como um valor de cadeia de caracteres de consulta. O ? em "{searchString?}" significa que esse é um parâmetro de rota opcional.

Exibição de índice com a palavra “ghost” adicionada à URL e uma lista de filmes retornados com dois filmes, Ghostbusters e Ghostbusters 2

O runtime do ASP.NET Core usa o model binding para definir o valor da propriedade SearchString na cadeia de consulta (?searchString=Ghost) ou nos dados de rota (https://localhost:5001/Movies/Ghost). O model binding não diferencia maiúsculas de minúsculas.

No entanto, você não pode esperar que os usuários modifiquem a URL para pesquisar um filme. Nesta etapa, a interface do usuário é adicionada para filtrar filmes. Se você adicionou a restrição de rota "{searchString?}", remova-a.

Abra o arquivo Pages/Movies/Index.cshtml e adicione a marcação realçada no seguinte código:

@page
@model RazorPagesMovie.Pages.Movies.IndexModel

@{
    ViewData["Title"] = "Index";
}

<h1>Index</h1>

<p>
    <a asp-page="Create">Create New</a>
</p>

<form>
    <p>
        <label>Title: <input type="text" asp-for="SearchString" /></label>
        <input type="submit" value="Filter" />
    </p>
</form>

<table class="table">
    <thead>

A marca <form> HTML usa os seguintes Auxiliares de Marcas:

Salve as alterações e teste o filtro.

Exibição de índice com a palavra “ghost” digitada na caixa de texto Filtro de título

Pesquisar por gênero

Atualize o método da Movies/Index.cshtml.cs página OnGetAsync com o seguinte código:

public async Task OnGetAsync()
{
    // <snippet_search_linqQuery>
    IQueryable<string> genreQuery = from m in _context.Movie
                                    orderby m.Genre
                                    select m.Genre;
    // </snippet_search_linqQuery>

    var movies = from m in _context.Movie
                 select m;

    if (!string.IsNullOrEmpty(SearchString))
    {
        movies = movies.Where(s => s.Title.Contains(SearchString));
    }

    if (!string.IsNullOrEmpty(MovieGenre))
    {
        movies = movies.Where(x => x.Genre == MovieGenre);
    }

    // <snippet_search_selectList>
    Genres = new SelectList(await genreQuery.Distinct().ToListAsync());
    // </snippet_search_selectList>
    Movie = await movies.ToListAsync();
}

O código a seguir é uma consulta LINQ que recupera todos os gêneros do banco de dados.

IQueryable<string> genreQuery = from m in _context.Movie
                                orderby m.Genre
                                select m.Genre;

A SelectList de gêneros é criada com a projeção dos gêneros distintos:

Genres = new SelectList(await genreQuery.Distinct().ToListAsync());

Adicionar pesquisa por gênero ao Razor Page

Atualize o elemento <form> de Index.cshtml conforme realçado na seguinte marcação:

@page
@model RazorPagesMovie.Pages.Movies.IndexModel

@{
    ViewData["Title"] = "Index";
}

<h1>Index</h1>

<p>
    <a asp-page="Create">Create New</a>
</p>

<form>
    <p>
        <select asp-for="MovieGenre" asp-items="Model.Genres">
            <option value="">All</option>
        </select>
        <label>Title: <input type="text" asp-for="SearchString" /></label>
        <input type="submit" value="Filter" />
    </p>
</form>

Teste o aplicativo pesquisando por gênero, título do filme e por ambos:

Exibição de índice concluída com filtros de pesquisa da caixa de texto Título e Seletor de gênero

Próximas etapas

Nas seções a seguir, a pesquisa de filmes por gênero ou nome é adicionada.

Adicione o código realçado a seguir a Pages/Movies/Index.cshtml.cs:

public class IndexModel : PageModel
{
    private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;

    public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
    {
        _context = context;
    }

    public IList<Movie> Movie { get;set; }  = default!;

    [BindProperty(SupportsGet = true)]
    public string? SearchString { get; set; }

    public SelectList? Genres { get; set; }

    [BindProperty(SupportsGet = true)]
    public string? MovieGenre { get; set; }

No código anterior:

  • SearchString: contém o texto que os usuários inserem na caixa de texto de pesquisa. SearchString tem o atributo [BindProperty]. [BindProperty] associa valores de formulário e cadeias de consulta ao mesmo nome da propriedade. [BindProperty(SupportsGet = true)] é necessário para a associação em solicitações HTTP GET.
  • Genres: contém a lista de gêneros. Genres permite que o usuário selecione um gênero na lista. SelectList exige using Microsoft.AspNetCore.Mvc.Rendering;
  • MovieGenre: contém o gênero específico selecionado pelo usuário. Por exemplo, "Faroreste".
  • Genres e MovieGenre são abordados mais adiante neste tutorial.

Aviso

Por motivos de segurança, você deve aceitar associar os dados da solicitação GET às propriedades do modelo de página. Verifique a entrada do usuário antes de mapeá-la para as propriedades. Aceitar a associação de GET é útil ao lidar com cenários que contam com a cadeia de caracteres de consulta ou com os valores de rota.

Para associar uma propriedade a solicitações GET, defina a propriedade SupportsGet do atributo [BindProperty] como true:

[BindProperty(SupportsGet = true)]

Para obter mais informações, confira ASP.NET Core Community Standup: Bind on GET discussion (YouTube).

Atualize o método OnGetAsync da página de Índice pelo seguinte código:

public async Task OnGetAsync()
{
    var movies = from m in _context.Movie
                 select m;
    if (!string.IsNullOrEmpty(SearchString))
    {
        movies = movies.Where(s => s.Title.Contains(SearchString));
    }

    Movie = await movies.ToListAsync();
}

A primeira linha do método OnGetAsync cria uma consulta LINQ para selecionar os filmes:

// using System.Linq;
var movies = from m in _context.Movie
             select m;

A consulta é definida somente neste ponto; ela não foi executada no banco de dados.

Se a propriedade SearchString não é null nem vazia, a consulta de filmes é modificada para filtrar a cadeia de caracteres de pesquisa:

if (!string.IsNullOrEmpty(SearchString))
{
    movies = movies.Where(s => s.Title.Contains(SearchString));
}

O código s => s.Title.Contains() é uma Expressão Lambda. Lambdas são usados em consultas LINQ baseadas em método como argumentos para métodos de operadores de consulta padrão, como o método Where ou Contains. As consultas LINQ não são executadas quando são definidas ou no momento em que são modificadas com uma chamada a um método, como Where, Contains ou OrderBy. Em vez disso, a execução da consulta é adiada. A avaliação de uma expressão é atrasada até que seu valor realizado seja iterado ou o método ToListAsync seja chamado. Consulte Execução de consulta para obter mais informações.

Observação

O método Contains é executado no banco de dados, não no código C#. A diferenciação de maiúsculas e minúsculas na consulta depende do banco de dados e da ordenação. No SQL Server, Contains é mapeado para SQL LIKE, que não diferencia maiúsculas de minúsculas. O SQLite com a ordenação padrão combina instruções que diferenciam ou não maiúsculas e minúsculas, a depender da consulta. Para obter informações sobre como instruir as consultas SQLite a não diferenciar maiúsculas de minúsculas, consulte os seguintes itens:

Navegue até a página Filmes e acrescente uma cadeia de consulta, como ?searchString=Ghost, à URL. Por exemplo, https://localhost:5001/Movies?searchString=Ghost. Os filmes filtrados são exibidos.

Exibição de índice

Se o modelo de rota a seguir for adicionado à página de Índice, a cadeia de caracteres de pesquisa poderá ser passada como um segmento de URL. Por exemplo, https://localhost:5001/Movies/Ghost.

@page "{searchString?}"

A restrição da rota anterior permite a pesquisa do título como dados de rota (um segmento de URL), em vez de como um valor de cadeia de caracteres de consulta. O ? em "{searchString?}" significa que esse é um parâmetro de rota opcional.

Exibição de índice com a palavra “ghost” adicionada à URL e uma lista de filmes retornados com dois filmes, Ghostbusters e Ghostbusters 2

O runtime do ASP.NET Core usa o model binding para definir o valor da propriedade SearchString na cadeia de consulta (?searchString=Ghost) ou nos dados de rota (https://localhost:5001/Movies/Ghost). O model binding não diferencia maiúsculas de minúsculas.

No entanto, você não pode esperar que os usuários modifiquem a URL para pesquisar um filme. Nesta etapa, a interface do usuário é adicionada para filtrar filmes. Se você adicionou a restrição de rota "{searchString?}", remova-a.

Abra o arquivo Pages/Movies/Index.cshtml e adicione a marcação realçada no seguinte código:

@page
@model RazorPagesMovie.Pages.Movies.IndexModel

@{
    ViewData["Title"] = "Index";
}

<h1>Index</h1>

<p>
    <a asp-page="Create">Create New</a>
</p>

<form>
    <p>
        <label>Title: <input type="text" asp-for="SearchString" /></label>
        <input type="submit" value="Filter" />
    </p>
</form>

<table class="table">
    @*Markup removed for brevity.*@

A marca <form> HTML usa os seguintes Auxiliares de Marcas:

Salve as alterações e teste o filtro.

Exibição de índice com a palavra “ghost” digitada na caixa de texto Filtro de título

Pesquisar por gênero

Atualize o método da Movies/Index.cshtml.cs página OnGetAsync com o seguinte código:

public async Task OnGetAsync()
{
    // Use LINQ to get list of genres.
    IQueryable<string> genreQuery = from m in _context.Movie
                                    orderby m.Genre
                                    select m.Genre;

    var movies = from m in _context.Movie
                 select m;

    if (!string.IsNullOrEmpty(SearchString))
    {
        movies = movies.Where(s => s.Title.Contains(SearchString));
    }

    if (!string.IsNullOrEmpty(MovieGenre))
    {
        movies = movies.Where(x => x.Genre == MovieGenre);
    }
    Genres = new SelectList(await genreQuery.Distinct().ToListAsync());
    Movie = await movies.ToListAsync();
}

O código a seguir é uma consulta LINQ que recupera todos os gêneros do banco de dados.

// Use LINQ to get list of genres.
IQueryable<string> genreQuery = from m in _context.Movie
                                orderby m.Genre
                                select m.Genre;

O SelectList de gêneros é criado com a projeção dos gêneros distintos.

Genres = new SelectList(await genreQuery.Distinct().ToListAsync());

Adicionar pesquisa por gênero ao Razor Page

Atualize o elemento <form> de Index.cshtml conforme realçado na seguinte marcação:

@page
@model RazorPagesMovie.Pages.Movies.IndexModel

@{
    ViewData["Title"] = "Index";
}

<h1>Index</h1>

<p>
    <a asp-page="Create">Create New</a>
</p>

<form>
    <p>
        <select asp-for="MovieGenre" asp-items="Model.Genres">
            <option value="">All</option>
        </select>
        <label>Title: <input type="text" asp-for="SearchString" /></label>
        <input type="submit" value="Filter" />
    </p>
</form>

Teste o aplicativo pesquisando por gênero, título do filme e por ambos.

Próximas etapas

Nas seções a seguir, a pesquisa de filmes por gênero ou nome é adicionada.

Adicione o código realçado a seguir a Pages/Movies/Index.cshtml.cs:

public class IndexModel : PageModel
{
    private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;

    public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
    {
        _context = context;
    }

    public IList<Movie> Movie { get;set; }  = default!;

    [BindProperty(SupportsGet = true)]
    public string? SearchString { get; set; }

    public SelectList? Genres { get; set; }

    [BindProperty(SupportsGet = true)]
    public string? MovieGenre { get; set; }

No código anterior:

  • SearchString: contém o texto que os usuários inserem na caixa de texto de pesquisa. SearchString tem o atributo [BindProperty]. [BindProperty] associa valores de formulário e cadeias de consulta ao mesmo nome da propriedade. [BindProperty(SupportsGet = true)] é necessário para a associação em solicitações HTTP GET.
  • Genres: contém a lista de gêneros. Genres permite que o usuário selecione um gênero na lista. SelectList exige using Microsoft.AspNetCore.Mvc.Rendering;
  • MovieGenre: contém o gênero específico selecionado pelo usuário. Por exemplo, "Faroreste".
  • Genres e MovieGenre são abordados mais adiante neste tutorial.

Aviso

Por motivos de segurança, você deve aceitar associar os dados da solicitação GET às propriedades do modelo de página. Verifique a entrada do usuário antes de mapeá-la para as propriedades. Aceitar a associação de GET é útil ao lidar com cenários que contam com a cadeia de caracteres de consulta ou com os valores de rota.

Para associar uma propriedade a solicitações GET, defina a propriedade SupportsGet do atributo [BindProperty] como true:

[BindProperty(SupportsGet = true)]

Para obter mais informações, confira ASP.NET Core Community Standup: Bind on GET discussion (YouTube).

Atualize o método OnGetAsync da página de Índice pelo seguinte código:

public async Task OnGetAsync()
{
    var movies = from m in _context.Movie
                 select m;
    if (!string.IsNullOrEmpty(SearchString))
    {
        movies = movies.Where(s => s.Title.Contains(SearchString));
    }

    Movie = await movies.ToListAsync();
}

A primeira linha do método OnGetAsync cria uma consulta LINQ para selecionar os filmes:

// using System.Linq;
var movies = from m in _context.Movie
             select m;

A consulta é definida somente neste ponto; ela não foi executada no banco de dados.

Se a propriedade SearchString não é null nem vazia, a consulta de filmes é modificada para filtrar a cadeia de caracteres de pesquisa:

if (!string.IsNullOrEmpty(SearchString))
{
    movies = movies.Where(s => s.Title.Contains(SearchString));
}

O código s => s.Title.Contains() é uma Expressão Lambda. Lambdas são usados em consultas LINQ baseadas em método como argumentos para métodos de operadores de consulta padrão, como o método Where ou Contains. As consultas LINQ não são executadas quando são definidas ou no momento em que são modificadas com uma chamada a um método, como Where, Contains ou OrderBy. Em vez disso, a execução da consulta é adiada. A avaliação de uma expressão é atrasada até que seu valor realizado seja iterado ou o método ToListAsync seja chamado. Consulte Execução de consulta para obter mais informações.

Observação

O método Contains é executado no banco de dados, não no código C#. A diferenciação de maiúsculas e minúsculas na consulta depende do banco de dados e da ordenação. No SQL Server, Contains é mapeado para SQL LIKE, que não diferencia maiúsculas de minúsculas. O SQLite com a ordenação padrão combina instruções que diferenciam ou não maiúsculas e minúsculas, a depender da consulta. Para obter informações sobre como instruir as consultas SQLite a não diferenciar maiúsculas de minúsculas, consulte os seguintes itens:

Navegue até a página Filmes e acrescente uma cadeia de consulta, como ?searchString=Ghost, à URL. Por exemplo, https://localhost:5001/Movies?searchString=Ghost. Os filmes filtrados são exibidos.

Exibição de índice

Se o modelo de rota a seguir for adicionado à página de Índice, a cadeia de caracteres de pesquisa poderá ser passada como um segmento de URL. Por exemplo, https://localhost:5001/Movies/Ghost.

@page "{searchString?}"

A restrição da rota anterior permite a pesquisa do título como dados de rota (um segmento de URL), em vez de como um valor de cadeia de caracteres de consulta. O ? em "{searchString?}" significa que esse é um parâmetro de rota opcional.

Exibição de índice com a palavra “ghost” adicionada à URL e uma lista de filmes retornados com dois filmes, Ghostbusters e Ghostbusters 2

O runtime do ASP.NET Core usa o model binding para definir o valor da propriedade SearchString na cadeia de consulta (?searchString=Ghost) ou nos dados de rota (https://localhost:5001/Movies/Ghost). O model binding não diferencia maiúsculas de minúsculas.

No entanto, você não pode esperar que os usuários modifiquem a URL para pesquisar um filme. Nesta etapa, a interface do usuário é adicionada para filtrar filmes. Se você adicionou a restrição de rota "{searchString?}", remova-a.

Abra o arquivo Pages/Movies/Index.cshtml e adicione a marcação realçada no seguinte código:

@page
@model RazorPagesMovie.Pages.Movies.IndexModel

@{
    ViewData["Title"] = "Index";
}

<h1>Index</h1>

<p>
    <a asp-page="Create">Create New</a>
</p>

<form>
    <p>
        <label>Title: <input type="text" asp-for="SearchString" /></label>
        <input type="submit" value="Filter" />
    </p>
</form>

<table class="table">
    @*Markup removed for brevity.*@

A marca <form> HTML usa os seguintes Auxiliares de Marcas:

Salve as alterações e teste o filtro.

Exibição de índice com a palavra “ghost” digitada na caixa de texto Filtro de título

Pesquisar por gênero

Atualize o método OnGetAsync da página de Índice pelo seguinte código:

public async Task OnGetAsync()
{
    // Use LINQ to get list of genres.
    IQueryable<string> genreQuery = from m in _context.Movie
                                    orderby m.Genre
                                    select m.Genre;

    var movies = from m in _context.Movie
                 select m;

    if (!string.IsNullOrEmpty(SearchString))
    {
        movies = movies.Where(s => s.Title.Contains(SearchString));
    }

    if (!string.IsNullOrEmpty(MovieGenre))
    {
        movies = movies.Where(x => x.Genre == MovieGenre);
    }
    Genres = new SelectList(await genreQuery.Distinct().ToListAsync());
    Movie = await movies.ToListAsync();
}

O código a seguir é uma consulta LINQ que recupera todos os gêneros do banco de dados.

// Use LINQ to get list of genres.
IQueryable<string> genreQuery = from m in _context.Movie
                                orderby m.Genre
                                select m.Genre;

O SelectList de gêneros é criado com a projeção dos gêneros distintos.

Genres = new SelectList(await genreQuery.Distinct().ToListAsync());

Adicionar pesquisa por gênero ao Razor Page

Atualize o elemento <form> de Index.cshtml conforme realçado na seguinte marcação:

@page
@model RazorPagesMovie.Pages.Movies.IndexModel

@{
    ViewData["Title"] = "Index";
}

<h1>Index</h1>

<p>
    <a asp-page="Create">Create New</a>
</p>

<form>
    <p>
        <select asp-for="MovieGenre" asp-items="Model.Genres">
            <option value="">All</option>
        </select>
        <label>Title: <input type="text" asp-for="SearchString" /></label>
        <input type="submit" value="Filter" />
    </p>
</form>

Teste o aplicativo pesquisando por gênero, título do filme e por ambos.

Próximas etapas

Nas seções a seguir, a pesquisa de filmes por gênero ou nome é adicionada.

Adicione o código realçado a seguir a Pages/Movies/Index.cshtml.cs:

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
using RazorPagesMovie.Models;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace RazorPagesMovie.Pages.Movies
{
    public class IndexModel : PageModel
    {
        private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;

        public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
        {
            _context = context;
        }

        public IList<Movie> Movie { get;set; } = default!;
        [BindProperty(SupportsGet = true)]
        public string ? SearchString { get; set; }
        public SelectList ? Genres { get; set; }
        [BindProperty(SupportsGet = true)]
        public string ? MovieGenre { get; set; }

No código anterior:

  • SearchString: contém o texto que os usuários inserem na caixa de texto de pesquisa. SearchString tem o atributo [BindProperty]. [BindProperty] associa valores de formulário e cadeias de consulta ao mesmo nome da propriedade. [BindProperty(SupportsGet = true)] é necessário para a associação em solicitações HTTP GET.
  • Genres: contém a lista de gêneros. Genres permite que o usuário selecione um gênero na lista. SelectList exige using Microsoft.AspNetCore.Mvc.Rendering;
  • MovieGenre: contém o gênero específico selecionado pelo usuário. Por exemplo, "Faroreste".
  • Genres e MovieGenre são abordados mais adiante neste tutorial.

Aviso

Por motivos de segurança, você deve aceitar associar os dados da solicitação GET às propriedades do modelo de página. Verifique a entrada do usuário antes de mapeá-la para as propriedades. Aceitar a associação de GET é útil ao lidar com cenários que contam com a cadeia de caracteres de consulta ou com os valores de rota.

Para associar uma propriedade a solicitações GET, defina a propriedade SupportsGet do atributo [BindProperty] como true:

[BindProperty(SupportsGet = true)]

Para obter mais informações, confira ASP.NET Core Community Standup: Bind on GET discussion (YouTube).

Atualize o método OnGetAsync da página de Índice pelo seguinte código:

public async Task OnGetAsync()
{
    var movies = from m in _context.Movie
                 select m;
    if (!string.IsNullOrEmpty(SearchString))
    {
        movies = movies.Where(s => s.Title.Contains(SearchString));
    }

    Movie = await movies.ToListAsync();
}

A primeira linha do método OnGetAsync cria uma consulta LINQ para selecionar os filmes:

// using System.Linq;
var movies = from m in _context.Movie
             select m;

A consulta é definida somente neste ponto; ela não foi executada no banco de dados.

Se a propriedade SearchString não é nula nem vazia, a consulta de filmes é modificada para filtrar a cadeia de pesquisa:

if (!string.IsNullOrEmpty(SearchString))
{
    movies = movies.Where(s => s.Title.Contains(SearchString));
}

O código s => s.Title.Contains() é uma Expressão Lambda. Lambdas são usados em consultas LINQ baseadas em método como argumentos para métodos de operadores de consulta padrão, como o método Where ou Contains. As consultas LINQ não são executadas quando são definidas ou no momento em que são modificadas com uma chamada a um método, como Where, Contains ou OrderBy. Em vez disso, a execução da consulta é adiada. A avaliação de uma expressão é atrasada até que seu valor realizado seja iterado ou o método ToListAsync seja chamado. Consulte Execução de consulta para obter mais informações.

Observação

O método Contains é executado no banco de dados, não no código C#. A diferenciação de maiúsculas e minúsculas na consulta depende do banco de dados e da ordenação. No SQL Server, Contains é mapeado para SQL LIKE, que não diferencia maiúsculas de minúsculas. O SQLite com a ordenação padrão combina instruções que diferenciam ou não maiúsculas e minúsculas, a depender da consulta. Para obter informações sobre como instruir as consultas SQLite a não diferenciar maiúsculas de minúsculas, consulte os seguintes itens:

Navegue até a página Filmes e acrescente uma cadeia de consulta, como ?searchString=Ghost, à URL. Por exemplo, https://localhost:5001/Movies?searchString=Ghost. Os filmes filtrados são exibidos.

Exibição de índice

Se o modelo de rota a seguir for adicionado à página de Índice, a cadeia de caracteres de pesquisa poderá ser passada como um segmento de URL. Por exemplo, https://localhost:5001/Movies/Ghost.

@page "{searchString?}"

A restrição da rota anterior permite a pesquisa do título como dados de rota (um segmento de URL), em vez de como um valor de cadeia de caracteres de consulta. O ? em "{searchString?}" significa que esse é um parâmetro de rota opcional.

Exibição de índice com a palavra “ghost” adicionada à URL e uma lista de filmes retornados com dois filmes, Ghostbusters e Ghostbusters 2

O runtime do ASP.NET Core usa o model binding para definir o valor da propriedade SearchString na cadeia de consulta (?searchString=Ghost) ou nos dados de rota (https://localhost:5001/Movies/Ghost). O model binding não diferencia maiúsculas de minúsculas.

No entanto, você não pode esperar que os usuários modifiquem a URL para pesquisar um filme. Nesta etapa, a interface do usuário é adicionada para filtrar filmes. Se você adicionou a restrição de rota "{searchString?}", remova-a.

Abra o arquivo Pages/Movies/Index.cshtml e adicione a marcação realçada no seguinte código:

@page
@model RazorPagesMovie.Pages.Movies.IndexModel

@{
    ViewData["Title"] = "Index";
}

<h1>Index</h1>

<p>
    <a asp-page="Create">Create New</a>
</p>

<form>
    <p>
        <label>Title: <input type="text" asp-for="SearchString" /></label>
        <input type="submit" value="Filter" />
    </p>
</form>

<table class="table">
    @*Markup removed for brevity.*@

A marca <form> HTML usa os seguintes Auxiliares de Marcas:

Salve as alterações e teste o filtro.

Exibição de índice com a palavra “ghost” digitada na caixa de texto Filtro de título

Pesquisar por gênero

Atualize o método OnGetAsync da página de Índice pelo seguinte código:

public async Task OnGetAsync()
{
    // Use LINQ to get list of genres.
    IQueryable<string> genreQuery = from m in _context.Movie
                                    orderby m.Genre
                                    select m.Genre;

    var movies = from m in _context.Movie
                 select m;

    if (!string.IsNullOrEmpty(SearchString))
    {
        movies = movies.Where(s => s.Title.Contains(SearchString));
    }

    if (!string.IsNullOrEmpty(MovieGenre))
    {
        movies = movies.Where(x => x.Genre == MovieGenre);
    }
    Genres = new SelectList(await genreQuery.Distinct().ToListAsync());
    Movie = await movies.ToListAsync();
}

O código a seguir é uma consulta LINQ que recupera todos os gêneros do banco de dados.

// Use LINQ to get list of genres.
IQueryable<string> genreQuery = from m in _context.Movie
                                orderby m.Genre
                                select m.Genre;

O SelectList de gêneros é criado com a projeção dos gêneros distintos.

Genres = new SelectList(await genreQuery.Distinct().ToListAsync());

Adicionar pesquisa por gênero ao Razor Page

Atualize o elemento <form> de Index.cshtml conforme realçado na seguinte marcação:

@page
@model RazorPagesMovie.Pages.Movies.IndexModel

@{
    ViewData["Title"] = "Index";
}

<h1>Index</h1>

<p>
    <a asp-page="Create">Create New</a>
</p>

<form>
    <p>
        <select asp-for="MovieGenre" asp-items="Model.Genres">
            <option value="">All</option>
        </select>
        <label>Title: <input type="text" asp-for="SearchString" /></label>
        <input type="submit" value="Filter" />
    </p>
</form>

Teste o aplicativo pesquisando por gênero, título do filme e por ambos.

Próximas etapas

Nas seções a seguir, a pesquisa de filmes por gênero ou nome é adicionada.

Adicione o seguinte realçado usando a instrução e as propriedades a Pages/Movies/Index.cshtml.cs:

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
using RazorPagesMovie.Models;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace RazorPagesMovie.Pages.Movies
{

    public class IndexModel : PageModel
    {
        private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;

        public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
        {
            _context = context;
        }

        public IList<Movie> Movie { get; set; }
        [BindProperty(SupportsGet = true)]
        public string SearchString { get; set; }
        public SelectList Genres { get; set; }
        [BindProperty(SupportsGet = true)]
        public string MovieGenre { get; set; }

No código anterior:

  • SearchString: contém o texto que os usuários inserem na caixa de texto de pesquisa. SearchString tem o atributo [BindProperty]. [BindProperty] associa valores de formulário e cadeias de consulta ao mesmo nome da propriedade. [BindProperty(SupportsGet = true)] é necessário para a associação em solicitações HTTP GET.
  • Genres: contém a lista de gêneros. Genres permite que o usuário selecione um gênero na lista. SelectList exige using Microsoft.AspNetCore.Mvc.Rendering;
  • MovieGenre: contém o gênero específico selecionado pelo usuário. Por exemplo, "Faroreste".
  • Genres e MovieGenre são abordados mais adiante neste tutorial.

Aviso

Por motivos de segurança, você deve aceitar associar os dados da solicitação GET às propriedades do modelo de página. Verifique a entrada do usuário antes de mapeá-la para as propriedades. Aceitar a associação de GET é útil ao lidar com cenários que contam com a cadeia de caracteres de consulta ou com os valores de rota.

Para associar uma propriedade a solicitações GET, defina a propriedade SupportsGet do atributo [BindProperty] como true:

[BindProperty(SupportsGet = true)]

Para obter mais informações, confira ASP.NET Core Community Standup: Bind on GET discussion (YouTube).

Atualize o método OnGetAsync da página de Índice pelo seguinte código:

public async Task OnGetAsync()
{
    var movies = from m in _context.Movie
                 select m;
    if (!string.IsNullOrEmpty(SearchString))
    {
        movies = movies.Where(s => s.Title.Contains(SearchString));
    }

    Movie = await movies.ToListAsync();
}

A primeira linha do método OnGetAsync cria uma consulta LINQ para selecionar os filmes:

// using System.Linq;
var movies = from m in _context.Movie
             select m;

A consulta é definida somente neste ponto; ela não foi executada no banco de dados.

Se a propriedade SearchString não é nula nem vazia, a consulta de filmes é modificada para filtrar a cadeia de pesquisa:

if (!string.IsNullOrEmpty(SearchString))
{
    movies = movies.Where(s => s.Title.Contains(SearchString));
}

O código s => s.Title.Contains() é uma Expressão Lambda. Lambdas são usados em consultas LINQ baseadas em método como argumentos para métodos de operadores de consulta padrão, como o método Where ou Contains. As consultas LINQ não são executadas quando são definidas ou no momento em que são modificadas com uma chamada a um método, como Where, Contains ou OrderBy. Em vez disso, a execução da consulta é adiada. A avaliação de uma expressão é atrasada até que seu valor realizado seja iterado ou o método ToListAsync seja chamado. Consulte Execução de consulta para obter mais informações.

Observação

O método Contains é executado no banco de dados, não no código C#. A diferenciação de maiúsculas e minúsculas na consulta depende do banco de dados e da ordenação. No SQL Server, Contains é mapeado para SQL LIKE, que não diferencia maiúsculas de minúsculas. O SQLite com a ordenação padrão combina instruções que diferenciam ou não maiúsculas e minúsculas, a depender da consulta. Para obter informações sobre como instruir as consultas SQLite a não diferenciar maiúsculas de minúsculas, consulte os seguintes itens:

Navegue até a página Filmes e acrescente uma cadeia de consulta, como ?searchString=Ghost, à URL. Por exemplo, https://localhost:5001/Movies?searchString=Ghost. Os filmes filtrados são exibidos.

Exibição de índice

Se o modelo de rota a seguir for adicionado à página de Índice, a cadeia de caracteres de pesquisa poderá ser passada como um segmento de URL. Por exemplo, https://localhost:5001/Movies/Ghost.

@page "{searchString?}"

A restrição da rota anterior permite a pesquisa do título como dados de rota (um segmento de URL), em vez de como um valor de cadeia de caracteres de consulta. O ? em "{searchString?}" significa que esse é um parâmetro de rota opcional.

Exibição de índice com a palavra “ghost” adicionada à URL e uma lista de filmes retornados com dois filmes, Ghostbusters e Ghostbusters 2

O runtime do ASP.NET Core usa o model binding para definir o valor da propriedade SearchString na cadeia de consulta (?searchString=Ghost) ou nos dados de rota (https://localhost:5001/Movies/Ghost). O model binding não diferencia maiúsculas de minúsculas.

No entanto, você não pode esperar que os usuários modifiquem a URL para pesquisar um filme. Nesta etapa, a interface do usuário é adicionada para filtrar filmes. Se você adicionou a restrição de rota "{searchString?}", remova-a.

Abra o arquivo Pages/Movies/Index.cshtml e adicione a marcação realçada no seguinte código:

@page
@model RazorPagesMovie.Pages.Movies.IndexModel

@{
    ViewData["Title"] = "Index";
}

<h1>Index</h1>

<p>
    <a asp-page="Create">Create New</a>
</p>

<form>
    <p>
        <label>Title: <input type="text" asp-for="SearchString" /></label>
        <input type="submit" value="Filter" />
    </p>
</form>

<table class="table">
    @*Markup removed for brevity.*@

A marca <form> HTML usa os seguintes Auxiliares de Marcas:

Salve as alterações e teste o filtro.

Exibição de índice com a palavra “ghost” digitada na caixa de texto Filtro de título

Pesquisar por gênero

Atualize o método OnGetAsync da página de Índice pelo seguinte código:

public async Task OnGetAsync()
{
    // Use LINQ to get list of genres.
    IQueryable<string> genreQuery = from m in _context.Movie
                                    orderby m.Genre
                                    select m.Genre;

    var movies = from m in _context.Movie
                 select m;

    if (!string.IsNullOrEmpty(SearchString))
    {
        movies = movies.Where(s => s.Title.Contains(SearchString));
    }

    if (!string.IsNullOrEmpty(MovieGenre))
    {
        movies = movies.Where(x => x.Genre == MovieGenre);
    }
    Genres = new SelectList(await genreQuery.Distinct().ToListAsync());
    Movie = await movies.ToListAsync();
}

O código a seguir é uma consulta LINQ que recupera todos os gêneros do banco de dados.

// Use LINQ to get list of genres.
IQueryable<string> genreQuery = from m in _context.Movie
                                orderby m.Genre
                                select m.Genre;

O SelectList de gêneros é criado com a projeção dos gêneros distintos.

Genres = new SelectList(await genreQuery.Distinct().ToListAsync());

Adicionar pesquisa por gênero ao Razor Page

  1. Atualize o elemento <form> de Index.cshtml conforme realçado na seguinte marcação:

    @page
    @model RazorPagesMovie.Pages.Movies.IndexModel
    
    @{
        ViewData["Title"] = "Index";
    }
    
    <h1>Index</h1>
    
    <p>
        <a asp-page="Create">Create New</a>
    </p>
    
    <form>
        <p>
            <select asp-for="MovieGenre" asp-items="Model.Genres">
                <option value="">All</option>
            </select>
            <label>Title: <input type="text" asp-for="SearchString" /></label>
            <input type="submit" value="Filter" />
        </p>
    </form>
    
    <table class="table">
        @*Markup removed for brevity.*@
    
    
  2. Teste o aplicativo pesquisando por gênero, título do filme e por ambos.

Próximas etapas