Parte 6. Adición de búsqueda a Razor Pages de ASP.NET Core

Nota:

Esta no es la versión más reciente de este artículo. Para la versión actual, consulte la versión .NET 8 de este artículo.

Advertencia

Esta versión de ASP.NET Core ya no se admite. Para obtener más información, consulte la Directiva de soporte técnico de .NET y .NET Core. Para la versión actual, consulte la versión .NET 8 de este artículo.

Importante

Esta información hace referencia a un producto en versión preliminar, el cual puede sufrir importantes modificaciones antes de que se publique la versión comercial. Microsoft no proporciona ninguna garantía, expresa o implícita, con respecto a la información proporcionada aquí.

Para la versión actual, consulte la versión .NET 8 de este artículo.

Por Rick Anderson

En las secciones siguientes, se ha agregado la función de buscar películas por género o nombre.

Agregue el código resaltado siguiente 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; }

En el código anterior:

  • SearchString: contiene el texto que los usuarios escriben en el cuadro de texto de búsqueda. SearchString tiene el atributo [BindProperty]. [BindProperty] enlaza los valores del formulario y las cadenas de consulta con el mismo nombre que la propiedad. [BindProperty(SupportsGet = true)]bse necesita para el enlace de las solicitudes GET de HTTP.
  • Genres: contiene la lista de géneros. Genres permite al usuario seleccionar un género de la lista. SelectList requiere using Microsoft.AspNetCore.Mvc.Rendering;.
  • MovieGenre: Contiene el género específico que el usuario selecciona. Por ejemplo, "Western".
  • Genres y MovieGenre se utilizan posteriormente en este tutorial.

Advertencia

Por motivos de seguridad, debe participar en el enlace de datos de solicitud GET con las propiedades del modelo de página. Compruebe las entradas de los usuarios antes de asignarlas a las propiedades. Si participa en el enlace de GET, le puede ser útil al trabajar con escenarios que dependan de cadenas de consultas o valores de rutas.

Para enlazar una propiedad en solicitudes GET, establezca la propiedad SupportsGet del atributo [BindProperty] en true:

[BindProperty(SupportsGet = true)]

Para obtener más información, vea ASP.NET Core Community Standup: Bind on GET discussion (YouTube).

Actualice el método Movies/Index de la página OnGetAsync con el código siguiente:

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

La primera línea del método OnGetAsync crea una consulta LINQ para seleccionar las películas:

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

En este momento, solo se define la consulta y no se ejecuta en la base de datos.

Si la propiedad SearchString no es null ni está vacía, la consulta de películas se modifica para filtrar según la cadena de búsqueda:

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

El código s => s.Title.Contains() es una expresión lambda. Las lambdas se usan en consultas LINQ basadas en métodos como argumentos para métodos de operador de consulta estándar, tales como el método Where o Contains. Las consultas LINQ no se ejecutan cuando se definen ni cuando se modifican mediante una llamada a un método como Where, Contains o OrderBy. En su lugar, se aplaza la ejecución de la consulta. La evaluación de una expresión se aplaza hasta que su valor realizado se repite o se llama al método ToListAsync. Para más información, vea Query Execution (Ejecución de consultas).

Nota

El método Contains se ejecuta en la base de datos, no en el código de C#. La distinción entre mayúsculas y minúsculas en la consulta depende de la base de datos y la intercalación. En SQL Server, Contains se asigna a SQL LIKE, que distingue entre mayúsculas y minúsculas. SQLite con la intercalación predeterminada es una combinación que distingue mayúsculas y minúsculas y que no distingue mayúsculas y minúsculas, en función de la consulta. Para obtener información sobre cómo hacer que las consultas SQLite no distingan mayúsculas y minúsculas, vea lo siguiente:

Vaya a la página de películas y anexe una cadena de consulta como ?searchString=Ghost a la dirección URL. Por ejemplo, https://localhost:5001/Movies?searchString=Ghost. Se muestran las películas filtradas.

Vista de índice

Si se agrega la siguiente plantilla de ruta a la página Index, la cadena de búsqueda se puede pasar como un segmento de dirección URL. Por ejemplo, https://localhost:5001/Movies/Ghost.

@page "{searchString?}"

La restricción de ruta anterior permite buscar el título como datos de ruta (un segmento de dirección URL) en lugar de como un valor de cadena de consulta. El elemento ? de "{searchString?}" significa que se trata de un parámetro de ruta opcional.

Vista de índice con la palabra Ghost (Fantasma) agregada a la dirección URL y una lista de las películas obtenidas, con dos películas, Ghostbusters y Ghostbusters 2

El entorno de ejecución de ASP.NET Core usa el enlace de modelos para establecer el valor de la propiedad SearchString de la cadena de consulta (?searchString=Ghost) o de los datos de ruta (https://localhost:5001/Movies/Ghost). El enlace de modelos no distingue entre mayúsculas y minúsculas.

Sin embargo, no se puede esperar que los usuarios modifiquen la dirección URL para buscar una película. En este paso, se agrega la interfaz de usuario para filtrar las películas. Si ha agregado la restricción de ruta "{searchString?}", quítela.

Abra el archivo Pages/Movies/Index.cshtml y agregue el marcado resaltado en el siguiente 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>

La etiqueta HTML <form> usa los siguientes Asistentes de etiquetas:

Guarde los cambios y pruebe el filtro.

Vista de índice con la palabra Ghost (Fantasma) escrita en el cuadro de texto del filtro Title (Título)

Búsqueda por género

Actualice el método Movies/Index.cshtml.cs de la página OnGetAsync con el código siguiente:

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

El código siguiente es una consulta LINQ que recupera todos los géneros de la base de datos.

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

La SelectList de géneros se crea mediante la proyección de los distintos géneros:

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

Incorporación de búsqueda por género a una página de Razor

Actualice el Index.cshtmlelemento <form> de como se destaca en el marcado siguiente:

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

Pruebe la aplicación buscando por género, por título de la película y por ambos:

Vista de índice completa con filtros de búsqueda de selector de género y cuadro de texto Título

Pasos siguientes

En las secciones siguientes, se ha agregado la función de buscar películas por género o nombre.

Agregue el código resaltado siguiente 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; }

En el código anterior:

  • SearchString: contiene el texto que los usuarios escriben en el cuadro de texto de búsqueda. SearchString tiene el atributo [BindProperty]. [BindProperty] enlaza los valores del formulario y las cadenas de consulta con el mismo nombre que la propiedad. [BindProperty(SupportsGet = true)]bse necesita para el enlace de las solicitudes GET de HTTP.
  • Genres: contiene la lista de géneros. Genres permite al usuario seleccionar un género de la lista. SelectList requiere using Microsoft.AspNetCore.Mvc.Rendering;.
  • MovieGenre: Contiene el género específico que el usuario selecciona. Por ejemplo, "Western".
  • Genres y MovieGenre se utilizan posteriormente en este tutorial.

Advertencia

Por motivos de seguridad, debe participar en el enlace de datos de solicitud GET con las propiedades del modelo de página. Compruebe las entradas de los usuarios antes de asignarlas a las propiedades. Si participa en el enlace de GET, le puede ser útil al trabajar con escenarios que dependan de cadenas de consultas o valores de rutas.

Para enlazar una propiedad en solicitudes GET, establezca la propiedad SupportsGet del atributo [BindProperty] en true:

[BindProperty(SupportsGet = true)]

Para obtener más información, vea ASP.NET Core Community Standup: Bind on GET discussion (YouTube).

Actualice el método OnGetAsync de la página de índice con el código siguiente:

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

La primera línea del método OnGetAsync crea una consulta LINQ para seleccionar las películas:

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

En este momento, solo se define la consulta y no se ejecuta en la base de datos.

Si la propiedad SearchString no es null ni está vacía, la consulta de películas se modifica para filtrar según la cadena de búsqueda:

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

El código s => s.Title.Contains() es una expresión lambda. Las lambdas se usan en consultas LINQ basadas en métodos como argumentos para métodos de operador de consulta estándar, tales como el método Where o Contains. Las consultas LINQ no se ejecutan cuando se definen ni cuando se modifican mediante una llamada a un método como Where, Contains o OrderBy. En su lugar, se aplaza la ejecución de la consulta. La evaluación de una expresión se aplaza hasta que su valor realizado se repite o se llama al método ToListAsync. Para más información, vea Query Execution (Ejecución de consultas).

Nota

El método Contains se ejecuta en la base de datos, no en el código de C#. La distinción entre mayúsculas y minúsculas en la consulta depende de la base de datos y la intercalación. En SQL Server, Contains se asigna a SQL LIKE, que distingue entre mayúsculas y minúsculas. SQLite con la intercalación predeterminada es una combinación que distingue mayúsculas y minúsculas y que no distingue mayúsculas y minúsculas, en función de la consulta. Para obtener información sobre cómo hacer que las consultas SQLite no distingan mayúsculas y minúsculas, vea lo siguiente:

Vaya a la página de películas y anexe una cadena de consulta como ?searchString=Ghost a la dirección URL. Por ejemplo, https://localhost:5001/Movies?searchString=Ghost. Se muestran las películas filtradas.

Vista de índice

Si se agrega la siguiente plantilla de ruta a la página Index, la cadena de búsqueda se puede pasar como un segmento de dirección URL. Por ejemplo, https://localhost:5001/Movies/Ghost.

@page "{searchString?}"

La restricción de ruta anterior permite buscar el título como datos de ruta (un segmento de dirección URL) en lugar de como un valor de cadena de consulta. El elemento ? de "{searchString?}" significa que se trata de un parámetro de ruta opcional.

Vista de índice con la palabra Ghost (Fantasma) agregada a la dirección URL y una lista de las películas obtenidas, con dos películas, Ghostbusters y Ghostbusters 2

El entorno de ejecución de ASP.NET Core usa el enlace de modelos para establecer el valor de la propiedad SearchString de la cadena de consulta (?searchString=Ghost) o de los datos de ruta (https://localhost:5001/Movies/Ghost). El enlace de modelos no distingue entre mayúsculas y minúsculas.

Sin embargo, no se puede esperar que los usuarios modifiquen la dirección URL para buscar una película. En este paso, se agrega la interfaz de usuario para filtrar las películas. Si ha agregado la restricción de ruta "{searchString?}", quítela.

Abra el archivo Pages/Movies/Index.cshtml y agregue el marcado resaltado en el siguiente 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.*@

La etiqueta HTML <form> usa los siguientes Asistentes de etiquetas:

Guarde los cambios y pruebe el filtro.

Vista de índice con la palabra Ghost (Fantasma) escrita en el cuadro de texto del filtro Title (Título)

Búsqueda por género

Actualice el método Movies/Index.cshtml.cs de la página OnGetAsync con el código siguiente:

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

El código siguiente es una consulta LINQ que recupera todos los géneros de la base de datos.

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

La SelectList de géneros se crea mediante la proyección de los distintos géneros.

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

Incorporación de búsqueda por género a una página de Razor

Actualice el Index.cshtmlelemento <form> de como se destaca en el marcado siguiente:

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

Pruebe la aplicación al buscar por género, título de la película y ambos.

Pasos siguientes

En las secciones siguientes, se ha agregado la función de buscar películas por género o nombre.

Agregue el código resaltado siguiente 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; }

En el código anterior:

  • SearchString: contiene el texto que los usuarios escriben en el cuadro de texto de búsqueda. SearchString tiene el atributo [BindProperty]. [BindProperty] enlaza los valores del formulario y las cadenas de consulta con el mismo nombre que la propiedad. [BindProperty(SupportsGet = true)]bse necesita para el enlace de las solicitudes GET de HTTP.
  • Genres: contiene la lista de géneros. Genres permite al usuario seleccionar un género de la lista. SelectList requiere using Microsoft.AspNetCore.Mvc.Rendering;.
  • MovieGenre: Contiene el género específico que el usuario selecciona. Por ejemplo, "Western".
  • Genres y MovieGenre se utilizan posteriormente en este tutorial.

Advertencia

Por motivos de seguridad, debe participar en el enlace de datos de solicitud GET con las propiedades del modelo de página. Compruebe las entradas de los usuarios antes de asignarlas a las propiedades. Si participa en el enlace de GET, le puede ser útil al trabajar con escenarios que dependan de cadenas de consultas o valores de rutas.

Para enlazar una propiedad en solicitudes GET, establezca la propiedad SupportsGet del atributo [BindProperty] en true:

[BindProperty(SupportsGet = true)]

Para obtener más información, vea ASP.NET Core Community Standup: Bind on GET discussion (YouTube).

Actualice el método OnGetAsync de la página de índice con el código siguiente:

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

La primera línea del método OnGetAsync crea una consulta LINQ para seleccionar las películas:

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

En este momento, solo se define la consulta y no se ejecuta en la base de datos.

Si la propiedad SearchString no es null ni está vacía, la consulta de películas se modifica para filtrar según la cadena de búsqueda:

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

El código s => s.Title.Contains() es una expresión lambda. Las lambdas se usan en consultas LINQ basadas en métodos como argumentos para métodos de operador de consulta estándar, tales como el método Where o Contains. Las consultas LINQ no se ejecutan cuando se definen ni cuando se modifican mediante una llamada a un método como Where, Contains o OrderBy. En su lugar, se aplaza la ejecución de la consulta. La evaluación de una expresión se aplaza hasta que su valor realizado se repite o se llama al método ToListAsync. Para más información, vea Query Execution (Ejecución de consultas).

Nota

El método Contains se ejecuta en la base de datos, no en el código de C#. La distinción entre mayúsculas y minúsculas en la consulta depende de la base de datos y la intercalación. En SQL Server, Contains se asigna a SQL LIKE, que distingue entre mayúsculas y minúsculas. SQLite con la intercalación predeterminada es una combinación que distingue mayúsculas y minúsculas y que no distingue mayúsculas y minúsculas, en función de la consulta. Para obtener información sobre cómo hacer que las consultas SQLite no distingan mayúsculas y minúsculas, vea lo siguiente:

Vaya a la página de películas y anexe una cadena de consulta como ?searchString=Ghost a la dirección URL. Por ejemplo, https://localhost:5001/Movies?searchString=Ghost. Se muestran las películas filtradas.

Vista de índice

Si se agrega la siguiente plantilla de ruta a la página Index, la cadena de búsqueda se puede pasar como un segmento de dirección URL. Por ejemplo, https://localhost:5001/Movies/Ghost.

@page "{searchString?}"

La restricción de ruta anterior permite buscar el título como datos de ruta (un segmento de dirección URL) en lugar de como un valor de cadena de consulta. El elemento ? de "{searchString?}" significa que se trata de un parámetro de ruta opcional.

Vista de índice con la palabra Ghost (Fantasma) agregada a la dirección URL y una lista de las películas obtenidas, con dos películas, Ghostbusters y Ghostbusters 2

El entorno de ejecución de ASP.NET Core usa el enlace de modelos para establecer el valor de la propiedad SearchString de la cadena de consulta (?searchString=Ghost) o de los datos de ruta (https://localhost:5001/Movies/Ghost). El enlace de modelos no distingue entre mayúsculas y minúsculas.

Sin embargo, no se puede esperar que los usuarios modifiquen la dirección URL para buscar una película. En este paso, se agrega la interfaz de usuario para filtrar las películas. Si ha agregado la restricción de ruta "{searchString?}", quítela.

Abra el archivo Pages/Movies/Index.cshtml y agregue el marcado resaltado en el siguiente 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.*@

La etiqueta HTML <form> usa los siguientes Asistentes de etiquetas:

Guarde los cambios y pruebe el filtro.

Vista de índice con la palabra Ghost (Fantasma) escrita en el cuadro de texto del filtro Title (Título)

Búsqueda por género

Actualice el método OnGetAsync de la página de índice con el código siguiente:

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

El código siguiente es una consulta LINQ que recupera todos los géneros de la base de datos.

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

La SelectList de géneros se crea mediante la proyección de los distintos géneros.

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

Incorporación de búsqueda por género a una página de Razor

Actualice el Index.cshtmlelemento <form> de como se destaca en el marcado siguiente:

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

Pruebe la aplicación al buscar por género, título de la película y ambos.

Pasos siguientes

En las secciones siguientes, se ha agregado la función de buscar películas por género o nombre.

Agregue el código resaltado siguiente 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; }

En el código anterior:

  • SearchString: contiene el texto que los usuarios escriben en el cuadro de texto de búsqueda. SearchString tiene el atributo [BindProperty]. [BindProperty] enlaza los valores del formulario y las cadenas de consulta con el mismo nombre que la propiedad. [BindProperty(SupportsGet = true)]bse necesita para el enlace de las solicitudes GET de HTTP.
  • Genres: contiene la lista de géneros. Genres permite al usuario seleccionar un género de la lista. SelectList requiere using Microsoft.AspNetCore.Mvc.Rendering;.
  • MovieGenre: Contiene el género específico que el usuario selecciona. Por ejemplo, "Western".
  • Genres y MovieGenre se utilizan posteriormente en este tutorial.

Advertencia

Por motivos de seguridad, debe participar en el enlace de datos de solicitud GET con las propiedades del modelo de página. Compruebe las entradas de los usuarios antes de asignarlas a las propiedades. Si participa en el enlace de GET, le puede ser útil al trabajar con escenarios que dependan de cadenas de consultas o valores de rutas.

Para enlazar una propiedad en solicitudes GET, establezca la propiedad SupportsGet del atributo [BindProperty] en true:

[BindProperty(SupportsGet = true)]

Para obtener más información, vea ASP.NET Core Community Standup: Bind on GET discussion (YouTube).

Actualice el método OnGetAsync de la página de índice con el código siguiente:

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

La primera línea del método OnGetAsync crea una consulta LINQ para seleccionar las películas:

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

En este momento, solo se define la consulta y no se ejecuta en la base de datos.

Si la propiedad SearchString no es NULL ni está vacía, la consulta de películas se modifica para filtrar según la cadena de búsqueda:

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

El código s => s.Title.Contains() es una expresión lambda. Las lambdas se usan en consultas LINQ basadas en métodos como argumentos para métodos de operador de consulta estándar, tales como el método Where o Contains. Las consultas LINQ no se ejecutan cuando se definen ni cuando se modifican mediante una llamada a un método como Where, Contains o OrderBy. En su lugar, se aplaza la ejecución de la consulta. La evaluación de una expresión se aplaza hasta que su valor realizado se repite o se llama al método ToListAsync. Para más información, vea Query Execution (Ejecución de consultas).

Nota

El método Contains se ejecuta en la base de datos, no en el código de C#. La distinción entre mayúsculas y minúsculas en la consulta depende de la base de datos y la intercalación. En SQL Server, Contains se asigna a SQL LIKE, que distingue entre mayúsculas y minúsculas. SQLite con la intercalación predeterminada es una combinación que distingue mayúsculas y minúsculas y que no distingue mayúsculas y minúsculas, en función de la consulta. Para obtener información sobre cómo hacer que las consultas SQLite no distingan mayúsculas y minúsculas, vea lo siguiente:

Vaya a la página de películas y anexe una cadena de consulta como ?searchString=Ghost a la dirección URL. Por ejemplo, https://localhost:5001/Movies?searchString=Ghost. Se muestran las películas filtradas.

Vista de índice

Si se agrega la siguiente plantilla de ruta a la página Index, la cadena de búsqueda se puede pasar como un segmento de dirección URL. Por ejemplo, https://localhost:5001/Movies/Ghost.

@page "{searchString?}"

La restricción de ruta anterior permite buscar el título como datos de ruta (un segmento de dirección URL) en lugar de como un valor de cadena de consulta. El elemento ? de "{searchString?}" significa que se trata de un parámetro de ruta opcional.

Vista de índice con la palabra Ghost (Fantasma) agregada a la dirección URL y una lista de las películas obtenidas, con dos películas, Ghostbusters y Ghostbusters 2

El entorno de ejecución de ASP.NET Core usa el enlace de modelos para establecer el valor de la propiedad SearchString de la cadena de consulta (?searchString=Ghost) o de los datos de ruta (https://localhost:5001/Movies/Ghost). El enlace de modelos no distingue entre mayúsculas y minúsculas.

Sin embargo, no se puede esperar que los usuarios modifiquen la dirección URL para buscar una película. En este paso, se agrega la interfaz de usuario para filtrar las películas. Si ha agregado la restricción de ruta "{searchString?}", quítela.

Abra el archivo Pages/Movies/Index.cshtml y agregue el marcado resaltado en el siguiente 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.*@

La etiqueta HTML <form> usa los siguientes Asistentes de etiquetas:

Guarde los cambios y pruebe el filtro.

Vista de índice con la palabra Ghost (Fantasma) escrita en el cuadro de texto del filtro Title (Título)

Búsqueda por género

Actualice el método OnGetAsync de la página de índice con el código siguiente:

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

El código siguiente es una consulta LINQ que recupera todos los géneros de la base de datos.

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

La SelectList de géneros se crea mediante la proyección de los distintos géneros.

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

Incorporación de búsqueda por género a una página de Razor

Actualice el Index.cshtmlelemento <form> de como se destaca en el marcado siguiente:

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

Pruebe la aplicación al buscar por género, título de la película y ambos.

Pasos siguientes

En las secciones siguientes, se ha agregado la función de buscar películas por género o nombre.

Agregue la siguiente instrucción using resaltada y las propiedades 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; }

En el código anterior:

  • SearchString: contiene el texto que los usuarios escriben en el cuadro de texto de búsqueda. SearchString tiene el atributo [BindProperty]. [BindProperty] enlaza los valores del formulario y las cadenas de consulta con el mismo nombre que la propiedad. [BindProperty(SupportsGet = true)]bse necesita para el enlace de las solicitudes GET de HTTP.
  • Genres: contiene la lista de géneros. Genres permite al usuario seleccionar un género de la lista. SelectList requiere using Microsoft.AspNetCore.Mvc.Rendering;.
  • MovieGenre: Contiene el género específico que el usuario selecciona. Por ejemplo, "Western".
  • Genres y MovieGenre se utilizan posteriormente en este tutorial.

Advertencia

Por motivos de seguridad, debe participar en el enlace de datos de solicitud GET con las propiedades del modelo de página. Compruebe las entradas de los usuarios antes de asignarlas a las propiedades. Si participa en el enlace de GET, le puede ser útil al trabajar con escenarios que dependan de cadenas de consultas o valores de rutas.

Para enlazar una propiedad en solicitudes GET, establezca la propiedad SupportsGet del atributo [BindProperty] en true:

[BindProperty(SupportsGet = true)]

Para obtener más información, vea ASP.NET Core Community Standup: Bind on GET discussion (YouTube).

Actualice el método OnGetAsync de la página de índice con el código siguiente:

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

La primera línea del método OnGetAsync crea una consulta LINQ para seleccionar las películas:

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

En este momento, solo se define la consulta y no se ejecuta en la base de datos.

Si la propiedad SearchString no es NULL ni está vacía, la consulta de películas se modifica para filtrar según la cadena de búsqueda:

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

El código s => s.Title.Contains() es una expresión lambda. Las lambdas se usan en consultas LINQ basadas en métodos como argumentos para métodos de operador de consulta estándar, tales como el método Where o Contains. Las consultas LINQ no se ejecutan cuando se definen ni cuando se modifican mediante una llamada a un método como Where, Contains o OrderBy. En su lugar, se aplaza la ejecución de la consulta. La evaluación de una expresión se aplaza hasta que su valor realizado se repite o se llama al método ToListAsync. Para más información, vea Query Execution (Ejecución de consultas).

Nota

El método Contains se ejecuta en la base de datos, no en el código de C#. La distinción entre mayúsculas y minúsculas en la consulta depende de la base de datos y la intercalación. En SQL Server, Contains se asigna a SQL LIKE, que distingue entre mayúsculas y minúsculas. SQLite con la intercalación predeterminada es una combinación que distingue mayúsculas y minúsculas y que no distingue mayúsculas y minúsculas, en función de la consulta. Para obtener información sobre cómo hacer que las consultas SQLite no distingan mayúsculas y minúsculas, vea lo siguiente:

Vaya a la página de películas y anexe una cadena de consulta como ?searchString=Ghost a la dirección URL. Por ejemplo, https://localhost:5001/Movies?searchString=Ghost. Se muestran las películas filtradas.

Vista de índice

Si se agrega la siguiente plantilla de ruta a la página Index, la cadena de búsqueda se puede pasar como un segmento de dirección URL. Por ejemplo, https://localhost:5001/Movies/Ghost.

@page "{searchString?}"

La restricción de ruta anterior permite buscar el título como datos de ruta (un segmento de dirección URL) en lugar de como un valor de cadena de consulta. El elemento ? de "{searchString?}" significa que se trata de un parámetro de ruta opcional.

Vista de índice con la palabra Ghost (Fantasma) agregada a la dirección URL y una lista de las películas obtenidas, con dos películas, Ghostbusters y Ghostbusters 2

El entorno de ejecución de ASP.NET Core usa el enlace de modelos para establecer el valor de la propiedad SearchString de la cadena de consulta (?searchString=Ghost) o de los datos de ruta (https://localhost:5001/Movies/Ghost). El enlace de modelos no distingue entre mayúsculas y minúsculas.

Sin embargo, no se puede esperar que los usuarios modifiquen la dirección URL para buscar una película. En este paso, se agrega la interfaz de usuario para filtrar las películas. Si ha agregado la restricción de ruta "{searchString?}", quítela.

Abra el archivo Pages/Movies/Index.cshtml y agregue el marcado resaltado en el siguiente 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.*@

La etiqueta HTML <form> usa los siguientes Asistentes de etiquetas:

Guarde los cambios y pruebe el filtro.

Vista de índice con la palabra Ghost (Fantasma) escrita en el cuadro de texto del filtro Title (Título)

Búsqueda por género

Actualice el método OnGetAsync de la página de índice con el código siguiente:

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

El código siguiente es una consulta LINQ que recupera todos los géneros de la base de datos.

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

La SelectList de géneros se crea mediante la proyección de los distintos géneros.

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

Incorporación de búsqueda por género a una página de Razor

  1. Actualice el Index.cshtmlelemento <form> de como se destaca en el marcado siguiente:

    @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. Pruebe la aplicación al buscar por género, título de la película y ambos.

Pasos siguientes