Parte 6, adicionar pesquisa a ASP.NET Core Razor páginasPart 6, add search to ASP.NET Core Razor Pages

De Rick AndersonBy Rick Anderson

Nas seções a seguir, a pesquisa de filmes por gênero ou nome é adicionada.In the following sections, searching movies by genre or name is added.

Adicione o seguinte realçado usando a instrução e as propriedades a pages/Movies/ Index . cshtml.cs:Add the following highlighted using statement and properties to 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:In the previous code:

  • SearchString: Contém o texto que os usuários inserem na caixa de texto de pesquisa.SearchString: Contains the text users enter in the search text box. SearchString tem o [BindProperty] atributo.SearchString has the [BindProperty] attribute. [BindProperty] associa valores de formulário e cadeias de consulta ao mesmo nome da propriedade.[BindProperty] binds form values and query strings with the same name as the property. [BindProperty(SupportsGet = true)] é necessário para a associação em solicitações HTTP GET.[BindProperty(SupportsGet = true)] is required for binding on HTTP GET requests.
  • Genres: Contém a lista de gêneros.Genres: Contains the list of genres. Genres permite que o usuário selecione um gênero na lista.Genres allows the user to select a genre from the list. SelectList exige using Microsoft.AspNetCore.Mvc.Rendering;SelectList requires using Microsoft.AspNetCore.Mvc.Rendering;
  • MovieGenre: Contém o gênero específico que o usuário seleciona.MovieGenre: Contains the specific genre the user selects. Por exemplo, "ocidental".For example, "Western".
  • Genres e MovieGenre são abordados mais adiante neste tutorial.Genres and MovieGenre are used later in this tutorial.

Aviso

Por motivos de segurança, você deve aceitar associar os dados da solicitação GET às propriedades do modelo de página.For security reasons, you must opt in to binding GET request data to page model properties. Verifique a entrada do usuário antes de mapeá-la para as propriedades.Verify user input before mapping it to properties. Optar GET pela associação é útil ao abordar cenários que dependem de cadeias de caracteres de consulta ou valores de rota.Opting into GET binding is useful when addressing scenarios that rely on query string or route values.

Para associar uma propriedade em GET solicitações, defina a [BindProperty] Propriedade do atributo SupportsGet como true :To bind a property on GET requests, set the [BindProperty] attribute's SupportsGet property to true:

[BindProperty(SupportsGet = true)]

Para obter mais informações, consulte ASP.NET Core Community encontros: associar em obter discussão (YouTube).For more information, see ASP.NET Core Community Standup: Bind on GET discussion (YouTube).

Atualize o Index método da página OnGetAsync com o seguinte código:Update the Index page's OnGetAsync method with the following code:

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:The first line of the OnGetAsync method creates a LINQ query to select the movies:

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

A consulta é apenas definida _ neste ponto, ela tem _ não foi executada no banco de dados.The query is only defined _ at this point, it has _ not been run against the database.

Se a propriedade SearchString não é nula nem vazia, a consulta de filmes é modificada para filtrar a cadeia de pesquisa:If the SearchString property is not null or empty, the movies query is modified to filter on the search string:

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

O código s => s.Title.Contains() é uma Expressão Lambda.The s => s.Title.Contains() code is a Lambda Expression. As Lambdas são usadas em consultas LINQ baseadas em método como argumentos para métodos de operador de consulta padrão, como o método Where ou Contains .Lambdas are used in method-based LINQ queries as arguments to standard query operator methods such as the Where method or Contains. Consultas LINQ não são executadas quando são definidas ou quando são modificadas chamando um método, como Where , Contains ou OrderBy .LINQ queries are not executed when they're defined or when they're modified by calling a method, such as Where, Contains, or OrderBy. Em vez disso, a execução da consulta é adiada.Rather, query execution is deferred. A avaliação de uma expressão é atrasada até que seu valor percebido seja iterado ou o ToListAsync método seja chamado.The evaluation of an expression is delayed until its realized value is iterated over or the ToListAsync method is called. Consulte Execução de consulta para obter mais informações.See Query Execution for more information.

Observação

o método Contains é executado no banco de dados, não no código C#.The Contains method is run on the database, not in the C# code. A diferenciação de maiúsculas e minúsculas na consulta depende do banco de dados e da ordenação.The case sensitivity on the query depends on the database and the collation. No SQL Server, Contains é mapeado para SQL LIKE, que não diferencia maiúsculas de minúsculas.On SQL Server, Contains maps to SQL LIKE, which is case insensitive. No SQLite, com a ordenação padrão, ele diferencia maiúsculas de minúsculas.In SQLite, with the default collation, it's case sensitive.

Navegue até a página filmes e acrescente uma cadeia de caracteres de consulta, como ?searchString=Ghost à URL.Navigate to the Movies page and append a query string such as ?searchString=Ghost to the URL. Por exemplo, https://localhost:5001/Movies?searchString=Ghost.For example, https://localhost:5001/Movies?searchString=Ghost. Os filmes filtrados são exibidos.The filtered movies are displayed.

::: no-Loc (índice)::: exibição

Se o modelo de rota a seguir for adicionado à Index página, a cadeia de caracteres de pesquisa poderá ser passada como um segmento de URL.If the following route template is added to the Index page, the search string can be passed as a URL segment. Por exemplo, https://localhost:5001/Movies/Ghost.For example, 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.The preceding route constraint allows searching the title as route data (a URL segment) instead of as a query string value. O ? em "{searchString?}" significa que esse é um parâmetro de rota opcional.The ? in "{searchString?}" means this is an optional route parameter.

::: no-Loc (index)::: View com a palavra fantasma adicionada à URL e uma lista de filmes retornada de 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).The ASP.NET Core runtime uses model binding to set the value of the SearchString property from the query string (?searchString=Ghost) or route data (https://localhost:5001/Movies/Ghost). A associação de modelo não diferencia maiúsculas de minúsculas.Model binding is not case sensitive.

No entanto, não se espera que os usuários modifiquem a URL para pesquisar um filme.However, users cannot be expected to modify the URL to search for a movie. Nesta etapa, a interface do usuário é adicionada para filtrar filmes.In this step, UI is added to filter movies. Se você adicionou a restrição de rota "{searchString?}", remova-a.If you added the route constraint "{searchString?}", remove it.

Abra o arquivo pages/Movies/ Index . cshtml e adicione a marcação realçada no código a seguir:Open the Pages/Movies/Index.cshtml file, and add the markup highlighted in the following code:

@page
@model RazorPagesMovie.Pages.Movies.IndexModel

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

<h1>Index</h1>

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

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

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

A marca <form> HTML usa os seguintes Auxiliares de Marcas:The HTML <form> tag uses the following Tag Helpers:

Salve as alterações e teste o filtro.Save the changes and test the filter.

::: no-Loc (índice)::: exibição com a palavra fantasma digitada na caixa de texto filtro de título

Pesquisar por gêneroSearch by genre

Atualize o Index método da página OnGetAsync com o seguinte código:Update the Index page's OnGetAsync method with the following code:

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.The following code is a LINQ query that retrieves all the genres from the database.

// 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.The SelectList of genres is created by projecting the distinct genres.

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

Adicionar pesquisa por gênero à Razor páginaAdd search by genre to the Razor Page

  1. Atualize o <form> elemento Index . cshtml como realçado na seguinte marcação:Update the Index.cshtml <form> element as highlighted in the following markup:

    @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>
            Title: <input type="text" asp-for="SearchString" />
            <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.Test the app by searching by genre, by movie title, and by both.

Recursos adicionaisAdditional resources

Exiba ou baixe o código de exemplo (como baixar).View or download sample code (how to download).

Nas seções a seguir, a pesquisa de filmes por gênero ou nome é adicionada.In the following sections, searching movies by genre or name is added.

Adicione as seguintes propriedades realçadas a pages/Movies/ Index . cshtml.cs:Add the following highlighted properties to Pages/Movies/Index.cshtml.cs:

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

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

    public IList<Movie> Movie { get; set; }
    [BindProperty(SupportsGet = true)]
    public string SearchString { get; set; }
    // Requires using Microsoft.AspNetCore.Mvc.Rendering;
    public SelectList Genres { get; set; }
    [BindProperty(SupportsGet = true)]
    public string MovieGenre { get; set; }
  • SearchString: Contém o texto que os usuários inserem na caixa de texto de pesquisa.SearchString: Contains the text users enter in the search text box. SearchString tem o [BindProperty] atributo.SearchString has the [BindProperty] attribute. [BindProperty] associa valores de formulário e cadeias de consulta ao mesmo nome da propriedade.[BindProperty] binds form values and query strings with the same name as the property. [BindProperty(SupportsGet = true)] é necessário para a associação em solicitações HTTP GET.[BindProperty(SupportsGet = true)] is required for binding on HTTP GET requests.
  • Genres: Contém a lista de gêneros.Genres: Contains the list of genres. Genres permite que o usuário selecione um gênero na lista.Genres allows the user to select a genre from the list. SelectList exige using Microsoft.AspNetCore.Mvc.Rendering;SelectList requires using Microsoft.AspNetCore.Mvc.Rendering;
  • MovieGenre: Contém o gênero específico que o usuário seleciona.MovieGenre: Contains the specific genre the user selects. Por exemplo, "ocidental".For example, "Western".
  • Genres e MovieGenre são abordados mais adiante neste tutorial.Genres and MovieGenre are used later in this tutorial.

Aviso

Por motivos de segurança, você deve aceitar associar os dados da solicitação GET às propriedades do modelo de página.For security reasons, you must opt in to binding GET request data to page model properties. Verifique a entrada do usuário antes de mapeá-la para as propriedades.Verify user input before mapping it to properties. Optar GET pela associação é útil ao abordar cenários que dependem de cadeias de caracteres de consulta ou valores de rota.Opting into GET binding is useful when addressing scenarios that rely on query string or route values.

Para associar uma propriedade em GET solicitações, defina a [BindProperty] Propriedade do atributo SupportsGet como true :To bind a property on GET requests, set the [BindProperty] attribute's SupportsGet property to true:

[BindProperty(SupportsGet = true)]

Para obter mais informações, consulte ASP.NET Core Community encontros: associar em obter discussão (YouTube).For more information, see ASP.NET Core Community Standup: Bind on GET discussion (YouTube).

Atualize o Index método da página OnGetAsync com o seguinte código:Update the Index page's OnGetAsync method with the following code:

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:The first line of the OnGetAsync method creates a LINQ query to select the movies:

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

A consulta é somente definida neste ponto; ela não foi executada no banco de dados.The query is only defined at this point, it has not been run against the database.

Se a propriedade SearchString não é nula nem vazia, a consulta de filmes é modificada para filtrar a cadeia de pesquisa:If the SearchString property is not null or empty, the movies query is modified to filter on the search string:

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

O código s => s.Title.Contains() é uma Expressão Lambda.The s => s.Title.Contains() code is a Lambda Expression. As Lambdas são usadas em consultas LINQ baseadas em método como argumentos para métodos de operador de consulta padrão, como o método Where ou Contains .Lambdas are used in method-based LINQ queries as arguments to standard query operator methods such as the Where method or Contains. Consultas LINQ não são executadas quando são definidas ou quando são modificadas chamando um método, como Where Contains ou OrderBy .LINQ queries are not executed when they're defined or when they're modified by calling a method, such as Where, Contains or OrderBy. Em vez disso, a execução da consulta é adiada.Rather, query execution is deferred. A avaliação de uma expressão é atrasada até que seu valor percebido seja iterado ou o ToListAsync método seja chamado.The evaluation of an expression is delayed until its realized value is iterated over or the ToListAsync method is called. Consulte Execução de consulta para obter mais informações.See Query Execution for more information.

Observação: o método Contains é executado no banco de dados, não no código C#.Note: The Contains method is run on the database, not in the C# code. A diferenciação de maiúsculas e minúsculas na consulta depende do banco de dados e da ordenação.The case sensitivity on the query depends on the database and the collation. No SQL Server, Contains é mapeado para SQL LIKE, que não diferencia maiúsculas de minúsculas.On SQL Server, Contains maps to SQL LIKE, which is case insensitive. No SQLite, com a ordenação padrão, ele diferencia maiúsculas de minúsculas.In SQLite, with the default collation, it's case sensitive.

Navegue até a página filmes e acrescente uma cadeia de caracteres de consulta, como ?searchString=Ghost à URL.Navigate to the Movies page and append a query string such as ?searchString=Ghost to the URL. Por exemplo, https://localhost:5001/Movies?searchString=Ghost.For example, https://localhost:5001/Movies?searchString=Ghost. Os filmes filtrados são exibidos.The filtered movies are displayed.

::: no-Loc (índice)::: exibição

Se o modelo de rota a seguir for adicionado à Index página, a cadeia de caracteres de pesquisa poderá ser passada como um segmento de URL.If the following route template is added to the Index page, the search string can be passed as a URL segment. Por exemplo, https://localhost:5001/Movies/Ghost.For example, 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.The preceding route constraint allows searching the title as route data (a URL segment) instead of as a query string value. O ? em "{searchString?}" significa que esse é um parâmetro de rota opcional.The ? in "{searchString?}" means this is an optional route parameter.

::: no-Loc (index)::: View com a palavra fantasma adicionada à URL e uma lista de filmes retornada de 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).The ASP.NET Core runtime uses model binding to set the value of the SearchString property from the query string (?searchString=Ghost) or route data (https://localhost:5001/Movies/Ghost). A associação de modelo não diferencia maiúsculas de minúsculas.Model binding is not case sensitive.

No entanto, não se espera que os usuários modifiquem a URL para pesquisar um filme.However, users can't be expected to modify the URL to search for a movie. Nesta etapa, a interface do usuário é adicionada para filtrar filmes.In this step, UI is added to filter movies. Se você adicionou a restrição de rota "{searchString?}", remova-a.If you added the route constraint "{searchString?}", remove it.

Abra o arquivo pages/Movies/ Index . cshtml e adicione a <form> marcação realçada no código a seguir:Open the Pages/Movies/Index.cshtml file, and add the <form> markup highlighted in the following code:

@page
@model RazorPagesMovie.Pages.Movies.IndexModel

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

<h1>Index</h1>

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

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

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

A marca <form> HTML usa os seguintes Auxiliares de Marcas:The HTML <form> tag uses the following Tag Helpers:

Salve as alterações e teste o filtro.Save the changes and test the filter.

::: no-Loc (índice)::: exibição com a palavra fantasma digitada na caixa de texto filtro de título

Pesquisar por gêneroSearch by genre

Atualize o método OnGetAsync pelo seguinte código:Update the OnGetAsync method with the following code:

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.The following code is a LINQ query that retrieves all the genres from the database.

// 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.The SelectList of genres is created by projecting the distinct genres.

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

Adicionar pesquisa por gênero à Razor páginaAdd search by genre to the Razor Page

Atualize o Index . cshtml [ <form> Element] ( https://developer.mozilla.org/docs/Web/HTML/Element/form) conforme realçado na seguinte marcação:Update the Index.cshtml [<form> element] (https://developer.mozilla.org/docs/Web/HTML/Element/form) as highlighted in the following markup:

@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>
        Title: <input type="text" asp-for="SearchString" />
        <input type="submit" value="Filter" />
    </p>
</form>

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

Teste o aplicativo pesquisando por gênero, título do filme e por ambos.Test the app by searching by genre, by movie title, and by both. O código anterior usa o auxiliar Select tag e a marca Option Helper.The preceding code uses the Select Tag Helper and Option Tag Helper.

Recursos adicionaisAdditional resources