Partager via


Partie 6, ajouter la recherche à ASP.NET Core Pages Razor

Remarque

Ceci n’est pas la dernière version de cet article. Pour la version actuelle, consultez la version .NET 8 de cet article.

Avertissement

Cette version d’ASP.NET Core n’est plus prise en charge. Pour plus d’informations, consultez la Stratégie de prise en charge de .NET et .NET Core. Pour la version actuelle, consultez la version .NET 8 de cet article.

Important

Ces informations portent sur la préversion du produit, qui est susceptible d’être en grande partie modifié avant sa commercialisation. Microsoft n’offre aucune garantie, expresse ou implicite, concernant les informations fournies ici.

Pour la version actuelle, consultez la version .NET 8 de cet article.

Par Rick Anderson

Dans les sections suivantes, la recherche de films par genre ou par nom est ajoutée.

Ajoutez le code en surbrillance suivant à 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; }

Dans le code précédent :

  • SearchString : Contient le texte que les utilisateurs entrent dans la zone de texte de recherche. SearchString a l’attribut [BindProperty]. [BindProperty] lie les valeurs de formulaire et les chaînes de requête avec le même nom que la propriété. [BindProperty(SupportsGet = true)] est obligatoire pour la liaison sur les requêtes HTTP GET.
  • Genres : Contient la liste des genres. Genres permet à l’utilisateur de sélectionner un genre dans la liste. SelectList nécessite using Microsoft.AspNetCore.Mvc.Rendering;
  • MovieGenre: Contient le genre spécifique sélectionné par l’utilisateur. Par exemple, « Western ».
  • Genres et MovieGenre sont utilisés plus loin dans ce tutoriel.

Avertissement

Pour des raisons de sécurité, vous devez choisir de lier les données de requête GET aux propriétés du modèle de page. Vérifiez l’entrée utilisateur avant de la mapper à des propriétés. Le choix de la liaison GET convient pour les scénarios qui s’appuient sur des valeurs de routage ou de chaîne de requête.

Pour lier une propriété sur des requêtes GET, définissez la propriété SupportsGet de l’attribut [BindProperty] sur true :

[BindProperty(SupportsGet = true)]

Pour plus d’informations, consultez ASP.NET Core Community Standup: Bind on GET discussion (YouTube).

Mettez à jour la méthode OnGetAsync de la page Movies/Index avec le code suivant :

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 première ligne de la méthode OnGetAsync crée une requête LINQ pour sélectionner les films :

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

La requête est seulement définie à ce stade, elle n’a pas été exécutée sur la base de données.

Si la propriété SearchString n’est pas null ou vide, la requête sur les films est modifiée de façon à filtrer sur la chaîne de recherche :

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

Le code s => s.Title.Contains() est une expression lambda. Les expressions lambda sont utilisées dans les requêtes LINQ basées sur une méthode en tant qu’arguments pour les méthodes d’opérateur de requête standard, comme la méthode Where ou Contains. Les requêtes LINQ ne sont pas exécutées quand elles sont définies ou quand elles sont modifiées en appelant une méthode, comme Where, Contains ou OrderBy. Au lieu de cela, l’exécution de la requête est différée. L’évaluation d’une expression est retardée jusqu’à ce que sa valeur réalisée fasse l’objet d’une itération réelle ou que la méthode ToListAsync soit appelée. Pour plus d’informations, consultez Exécution de requête.

Remarque

La méthode Contains est exécutée sur la base de données, et non pas dans le code C#. Le respect de la casse pour la requête dépend de la base de données et du classement. Sur SQL Server, Contains est mappée à SQL LIKE, qui ne respecte pas la casse. SQLite avec le classement par défaut est un mélange de respect de la casse et de respect de la casse IN, en fonction de la requête. Pour plus d’informations sur la création de requêtes SQLite sans respect de la casse, consultez les rubriques suivantes :

Accédez à la page Films, puis ajoutez une chaîne de requête telle que ?searchString=Ghost à l’URL. Par exemple, https://localhost:5001/Movies?searchString=Ghost Les films filtrés sont affichés.

Vue Index

Si le modèle de routage suivant est ajouté à la page d’index, la chaîne de recherche peut être passée comme un segment d’URL. Par exemple, https://localhost:5001/Movies/Ghost

@page "{searchString?}"

La contrainte d’itinéraire précédente permet de rechercher le titre comme données d’itinéraire (un segment d’URL) et non comme valeur de chaîne de requête. Le ? dans "{searchString?}" signifie qu’il s’agit d’un paramètre d’itinéraire facultatif.

Vue Index avec le mot « ghost » ajouté à l’URL et une liste de films retournée contenant deux films, Ghostbusters et Ghostbusters 2

Le runtime ASP.NET Core utilise la liaison de modèle pour définir la valeur de la propriété SearchString à partir de la chaîne de requête (?searchString=Ghost) ou des données de la route (https://localhost:5001/Movies/Ghost). La liaison de modèle ne respecte pas la casse.

Cependant, vous ne pouvez pas attendre des utilisateurs qu’ils modifient l’URL pour rechercher un film. Dans cette étape, une interface utilisateur est ajoutée pour filtrer les films. Si vous avez ajouté la contrainte d’itinéraire "{searchString?}", supprimez-la.

Ouvrez le fichier Pages/Movies/Index.cshtml, puis ajoutez la balise mise en surbrillance dans le code suivant :

@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 balise HTML <form> utilise les Tag Helpers suivants :

  • Tag Helper Form. Quand le formulaire est envoyé, la chaîne de filtrage est envoyée à la page Pages/Movies/Index via la chaîne de requête.
  • Tag Helper Input

Enregistrez les modifications apportées, puis testez le filtre.

Vue Index avec le mot « ghost » tapé dans la zone de texte de filtre des titres

Rechercher par genre

Mettez à jour la méthode OnGetAsync de la page Movies/Index.cshtml.cs avec le code suivant :

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

Le code suivant est une requête LINQ qui récupère tous les genres dans la base de données.

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

Le SelectList des genres est créé en projetant les genres distincts :

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

Ajoutez une recherche par genre à la Page Razor

Mettez à jour l'Index.cshtml <form> élément comme mis en évidence dans le balisage suivant :

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

Testez l’application en effectuant une recherche par genre, par titre de film et selon ces deux critères :

Affichage d’index complet avec sélecteur genre et filtres de recherche de zone de texte Titre

Étapes suivantes

Dans les sections suivantes, la recherche de films par genre ou par nom est ajoutée.

Ajoutez le code en surbrillance suivant à 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; }

Dans le code précédent :

  • SearchString : Contient le texte que les utilisateurs entrent dans la zone de texte de recherche. SearchString a l’attribut [BindProperty]. [BindProperty] lie les valeurs de formulaire et les chaînes de requête avec le même nom que la propriété. [BindProperty(SupportsGet = true)] est obligatoire pour la liaison sur les requêtes HTTP GET.
  • Genres : Contient la liste des genres. Genres permet à l’utilisateur de sélectionner un genre dans la liste. SelectList nécessite using Microsoft.AspNetCore.Mvc.Rendering;
  • MovieGenre: Contient le genre spécifique sélectionné par l’utilisateur. Par exemple, « Western ».
  • Genres et MovieGenre sont utilisés plus loin dans ce tutoriel.

Avertissement

Pour des raisons de sécurité, vous devez choisir de lier les données de requête GET aux propriétés du modèle de page. Vérifiez l’entrée utilisateur avant de la mapper à des propriétés. Le choix de la liaison GET convient pour les scénarios qui s’appuient sur des valeurs de routage ou de chaîne de requête.

Pour lier une propriété sur des requêtes GET, définissez la propriété SupportsGet de l’attribut [BindProperty] sur true :

[BindProperty(SupportsGet = true)]

Pour plus d’informations, consultez ASP.NET Core Community Standup: Bind on GET discussion (YouTube).

Mettez à jour la méthode OnGetAsync de la page Index avec le code suivant :

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 première ligne de la méthode OnGetAsync crée une requête LINQ pour sélectionner les films :

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

La requête est seulement définie à ce stade, elle n’a pas été exécutée sur la base de données.

Si la propriété SearchString n’est pas null ou vide, la requête sur les films est modifiée de façon à filtrer sur la chaîne de recherche :

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

Le code s => s.Title.Contains() est une expression lambda. Les expressions lambda sont utilisées dans les requêtes LINQ basées sur une méthode en tant qu’arguments pour les méthodes d’opérateur de requête standard, comme la méthode Where ou Contains. Les requêtes LINQ ne sont pas exécutées quand elles sont définies ou quand elles sont modifiées en appelant une méthode, comme Where, Contains ou OrderBy. Au lieu de cela, l’exécution de la requête est différée. L’évaluation d’une expression est retardée jusqu’à ce que sa valeur réalisée fasse l’objet d’une itération réelle ou que la méthode ToListAsync soit appelée. Pour plus d’informations, consultez Exécution de requête.

Remarque

La méthode Contains est exécutée sur la base de données, et non pas dans le code C#. Le respect de la casse pour la requête dépend de la base de données et du classement. Sur SQL Server, Contains est mappée à SQL LIKE, qui ne respecte pas la casse. SQLite avec le classement par défaut est un mélange de respect de la casse et de respect de la casse IN, en fonction de la requête. Pour plus d’informations sur la création de requêtes SQLite sans respect de la casse, consultez les rubriques suivantes :

Accédez à la page Films, puis ajoutez une chaîne de requête telle que ?searchString=Ghost à l’URL. Par exemple, https://localhost:5001/Movies?searchString=Ghost Les films filtrés sont affichés.

Vue Index

Si le modèle de routage suivant est ajouté à la page d’index, la chaîne de recherche peut être passée comme un segment d’URL. Par exemple, https://localhost:5001/Movies/Ghost

@page "{searchString?}"

La contrainte d’itinéraire précédente permet de rechercher le titre comme données d’itinéraire (un segment d’URL) et non comme valeur de chaîne de requête. Le ? dans "{searchString?}" signifie qu’il s’agit d’un paramètre d’itinéraire facultatif.

Vue Index avec le mot « ghost » ajouté à l’URL et une liste de films retournée contenant deux films, Ghostbusters et Ghostbusters 2

Le runtime ASP.NET Core utilise la liaison de modèle pour définir la valeur de la propriété SearchString à partir de la chaîne de requête (?searchString=Ghost) ou des données de la route (https://localhost:5001/Movies/Ghost). La liaison de modèle ne respecte pas la casse.

Cependant, vous ne pouvez pas attendre des utilisateurs qu’ils modifient l’URL pour rechercher un film. Dans cette étape, une interface utilisateur est ajoutée pour filtrer les films. Si vous avez ajouté la contrainte d’itinéraire "{searchString?}", supprimez-la.

Ouvrez le fichier Pages/Movies/Index.cshtml, puis ajoutez la balise mise en surbrillance dans le code suivant :

@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 balise HTML <form> utilise les Tag Helpers suivants :

  • Tag Helper Form. Quand le formulaire est envoyé, la chaîne de filtrage est envoyée à la page Pages/Movies/Index via la chaîne de requête.
  • Tag Helper Input

Enregistrez les modifications apportées, puis testez le filtre.

Vue Index avec le mot « ghost » tapé dans la zone de texte de filtre des titres

Rechercher par genre

Mettez à jour la méthode OnGetAsync de la page Movies/Index.cshtml.cs avec le code suivant :

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

Le code suivant est une requête LINQ qui récupère tous les genres dans la base de données.

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

La liste SelectList de genres est créée en projetant des différents genres.

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

Ajoutez une recherche par genre à la Page Razor

Mettez à jour l'Index.cshtml <form> élément comme mis en évidence dans le balisage suivant :

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

Testez l’application en effectuant une recherche par genre, par titre de film et selon ces deux critères.

Étapes suivantes

Dans les sections suivantes, la recherche de films par genre ou par nom est ajoutée.

Ajoutez le code en surbrillance suivant à 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; }

Dans le code précédent :

  • SearchString : Contient le texte que les utilisateurs entrent dans la zone de texte de recherche. SearchString a l’attribut [BindProperty]. [BindProperty] lie les valeurs de formulaire et les chaînes de requête avec le même nom que la propriété. [BindProperty(SupportsGet = true)] est obligatoire pour la liaison sur les requêtes HTTP GET.
  • Genres : Contient la liste des genres. Genres permet à l’utilisateur de sélectionner un genre dans la liste. SelectList nécessite using Microsoft.AspNetCore.Mvc.Rendering;
  • MovieGenre: Contient le genre spécifique sélectionné par l’utilisateur. Par exemple, « Western ».
  • Genres et MovieGenre sont utilisés plus loin dans ce tutoriel.

Avertissement

Pour des raisons de sécurité, vous devez choisir de lier les données de requête GET aux propriétés du modèle de page. Vérifiez l’entrée utilisateur avant de la mapper à des propriétés. Le choix de la liaison GET convient pour les scénarios qui s’appuient sur des valeurs de routage ou de chaîne de requête.

Pour lier une propriété sur des requêtes GET, définissez la propriété SupportsGet de l’attribut [BindProperty] sur true :

[BindProperty(SupportsGet = true)]

Pour plus d’informations, consultez ASP.NET Core Community Standup: Bind on GET discussion (YouTube).

Mettez à jour la méthode OnGetAsync de la page Index avec le code suivant :

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 première ligne de la méthode OnGetAsync crée une requête LINQ pour sélectionner les films :

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

La requête est seulement définie à ce stade, elle n’a pas été exécutée sur la base de données.

Si la propriété SearchString n’est pas null ou vide, la requête sur les films est modifiée de façon à filtrer sur la chaîne de recherche :

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

Le code s => s.Title.Contains() est une expression lambda. Les expressions lambda sont utilisées dans les requêtes LINQ basées sur une méthode en tant qu’arguments pour les méthodes d’opérateur de requête standard, comme la méthode Where ou Contains. Les requêtes LINQ ne sont pas exécutées quand elles sont définies ou quand elles sont modifiées en appelant une méthode, comme Where, Contains ou OrderBy. Au lieu de cela, l’exécution de la requête est différée. L’évaluation d’une expression est retardée jusqu’à ce que sa valeur réalisée fasse l’objet d’une itération réelle ou que la méthode ToListAsync soit appelée. Pour plus d’informations, consultez Exécution de requête.

Remarque

La méthode Contains est exécutée sur la base de données, et non pas dans le code C#. Le respect de la casse pour la requête dépend de la base de données et du classement. Sur SQL Server, Contains est mappée à SQL LIKE, qui ne respecte pas la casse. SQLite avec le classement par défaut est un mélange de respect de la casse et de respect de la casse IN, en fonction de la requête. Pour plus d’informations sur la création de requêtes SQLite sans respect de la casse, consultez les rubriques suivantes :

Accédez à la page Films, puis ajoutez une chaîne de requête telle que ?searchString=Ghost à l’URL. Par exemple, https://localhost:5001/Movies?searchString=Ghost Les films filtrés sont affichés.

Vue Index

Si le modèle de routage suivant est ajouté à la page d’index, la chaîne de recherche peut être passée comme un segment d’URL. Par exemple, https://localhost:5001/Movies/Ghost

@page "{searchString?}"

La contrainte d’itinéraire précédente permet de rechercher le titre comme données d’itinéraire (un segment d’URL) et non comme valeur de chaîne de requête. Le ? dans "{searchString?}" signifie qu’il s’agit d’un paramètre d’itinéraire facultatif.

Vue Index avec le mot « ghost » ajouté à l’URL et une liste de films retournée contenant deux films, Ghostbusters et Ghostbusters 2

Le runtime ASP.NET Core utilise la liaison de modèle pour définir la valeur de la propriété SearchString à partir de la chaîne de requête (?searchString=Ghost) ou des données de la route (https://localhost:5001/Movies/Ghost). La liaison de modèle ne respecte pas la casse.

Cependant, vous ne pouvez pas attendre des utilisateurs qu’ils modifient l’URL pour rechercher un film. Dans cette étape, une interface utilisateur est ajoutée pour filtrer les films. Si vous avez ajouté la contrainte d’itinéraire "{searchString?}", supprimez-la.

Ouvrez le fichier Pages/Movies/Index.cshtml, puis ajoutez la balise mise en surbrillance dans le code suivant :

@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 balise HTML <form> utilise les Tag Helpers suivants :

  • Tag Helper Form. Quand le formulaire est envoyé, la chaîne de filtrage est envoyée à la page Pages/Movies/Index via la chaîne de requête.
  • Tag Helper Input

Enregistrez les modifications apportées, puis testez le filtre.

Vue Index avec le mot « ghost » tapé dans la zone de texte de filtre des titres

Rechercher par genre

Mettez à jour la méthode OnGetAsync de la page Index avec le code suivant :

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

Le code suivant est une requête LINQ qui récupère tous les genres dans la base de données.

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

La liste SelectList de genres est créée en projetant des différents genres.

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

Ajoutez une recherche par genre à la Page Razor

Mettez à jour l'Index.cshtml <form> élément comme mis en évidence dans le balisage suivant :

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

Testez l’application en effectuant une recherche par genre, par titre de film et selon ces deux critères.

Étapes suivantes

Dans les sections suivantes, la recherche de films par genre ou par nom est ajoutée.

Ajoutez le code en surbrillance suivant à 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; }

Dans le code précédent :

  • SearchString : Contient le texte que les utilisateurs entrent dans la zone de texte de recherche. SearchString a l’attribut [BindProperty]. [BindProperty] lie les valeurs de formulaire et les chaînes de requête avec le même nom que la propriété. [BindProperty(SupportsGet = true)] est obligatoire pour la liaison sur les requêtes HTTP GET.
  • Genres : Contient la liste des genres. Genres permet à l’utilisateur de sélectionner un genre dans la liste. SelectList nécessite using Microsoft.AspNetCore.Mvc.Rendering;
  • MovieGenre: Contient le genre spécifique sélectionné par l’utilisateur. Par exemple, « Western ».
  • Genres et MovieGenre sont utilisés plus loin dans ce tutoriel.

Avertissement

Pour des raisons de sécurité, vous devez choisir de lier les données de requête GET aux propriétés du modèle de page. Vérifiez l’entrée utilisateur avant de la mapper à des propriétés. Le choix de la liaison GET convient pour les scénarios qui s’appuient sur des valeurs de routage ou de chaîne de requête.

Pour lier une propriété sur des requêtes GET, définissez la propriété SupportsGet de l’attribut [BindProperty] sur true :

[BindProperty(SupportsGet = true)]

Pour plus d’informations, consultez ASP.NET Core Community Standup: Bind on GET discussion (YouTube).

Mettez à jour la méthode OnGetAsync de la page Index avec le code suivant :

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 première ligne de la méthode OnGetAsync crée une requête LINQ pour sélectionner les films :

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

La requête est seulement définie à ce stade, elle n’a pas été exécutée sur la base de données.

Si la propriété SearchString n’est pas nulle ou vide, la requête sur les films est modifiée de façon à filtrer sur la chaîne de recherche :

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

Le code s => s.Title.Contains() est une expression lambda. Les expressions lambda sont utilisées dans les requêtes LINQ basées sur une méthode en tant qu’arguments pour les méthodes d’opérateur de requête standard, comme la méthode Where ou Contains. Les requêtes LINQ ne sont pas exécutées quand elles sont définies ou quand elles sont modifiées en appelant une méthode, comme Where, Contains ou OrderBy. Au lieu de cela, l’exécution de la requête est différée. L’évaluation d’une expression est retardée jusqu’à ce que sa valeur réalisée fasse l’objet d’une itération réelle ou que la méthode ToListAsync soit appelée. Pour plus d’informations, consultez Exécution de requête.

Remarque

La méthode Contains est exécutée sur la base de données, et non pas dans le code C#. Le respect de la casse pour la requête dépend de la base de données et du classement. Sur SQL Server, Contains est mappée à SQL LIKE, qui ne respecte pas la casse. SQLite avec le classement par défaut est un mélange de respect de la casse et de respect de la casse IN, en fonction de la requête. Pour plus d’informations sur la création de requêtes SQLite sans respect de la casse, consultez les rubriques suivantes :

Accédez à la page Films, puis ajoutez une chaîne de requête telle que ?searchString=Ghost à l’URL. Par exemple, https://localhost:5001/Movies?searchString=Ghost Les films filtrés sont affichés.

Vue Index

Si le modèle de routage suivant est ajouté à la page d’index, la chaîne de recherche peut être passée comme un segment d’URL. Par exemple, https://localhost:5001/Movies/Ghost

@page "{searchString?}"

La contrainte d’itinéraire précédente permet de rechercher le titre comme données d’itinéraire (un segment d’URL) et non comme valeur de chaîne de requête. Le ? dans "{searchString?}" signifie qu’il s’agit d’un paramètre d’itinéraire facultatif.

Vue Index avec le mot « ghost » ajouté à l’URL et une liste de films retournée contenant deux films, Ghostbusters et Ghostbusters 2

Le runtime ASP.NET Core utilise la liaison de modèle pour définir la valeur de la propriété SearchString à partir de la chaîne de requête (?searchString=Ghost) ou des données de la route (https://localhost:5001/Movies/Ghost). La liaison de modèle ne respecte pas la casse.

Cependant, vous ne pouvez pas attendre des utilisateurs qu’ils modifient l’URL pour rechercher un film. Dans cette étape, une interface utilisateur est ajoutée pour filtrer les films. Si vous avez ajouté la contrainte d’itinéraire "{searchString?}", supprimez-la.

Ouvrez le fichier Pages/Movies/Index.cshtml, puis ajoutez la balise mise en surbrillance dans le code suivant :

@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 balise HTML <form> utilise les Tag Helpers suivants :

  • Tag Helper Form. Quand le formulaire est envoyé, la chaîne de filtrage est envoyée à la page Pages/Movies/Index via la chaîne de requête.
  • Tag Helper Input

Enregistrez les modifications apportées, puis testez le filtre.

Vue Index avec le mot « ghost » tapé dans la zone de texte de filtre des titres

Rechercher par genre

Mettez à jour la méthode OnGetAsync de la page Index avec le code suivant :

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

Le code suivant est une requête LINQ qui récupère tous les genres dans la base de données.

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

La liste SelectList de genres est créée en projetant des différents genres.

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

Ajoutez une recherche par genre à la Page Razor

Mettez à jour l'Index.cshtml <form> élément comme mis en évidence dans le balisage suivant :

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

Testez l’application en effectuant une recherche par genre, par titre de film et selon ces deux critères.

Étapes suivantes

Dans les sections suivantes, la recherche de films par genre ou par nom est ajoutée.

Ajoutez les éléments suivants mis en surbrillance à l’aide de l’instruction et des propriétés à 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; }

Dans le code précédent :

  • SearchString : Contient le texte que les utilisateurs entrent dans la zone de texte de recherche. SearchString a l’attribut [BindProperty]. [BindProperty] lie les valeurs de formulaire et les chaînes de requête avec le même nom que la propriété. [BindProperty(SupportsGet = true)] est obligatoire pour la liaison sur les requêtes HTTP GET.
  • Genres : Contient la liste des genres. Genres permet à l’utilisateur de sélectionner un genre dans la liste. SelectList nécessite using Microsoft.AspNetCore.Mvc.Rendering;
  • MovieGenre: Contient le genre spécifique sélectionné par l’utilisateur. Par exemple, « Western ».
  • Genres et MovieGenre sont utilisés plus loin dans ce tutoriel.

Avertissement

Pour des raisons de sécurité, vous devez choisir de lier les données de requête GET aux propriétés du modèle de page. Vérifiez l’entrée utilisateur avant de la mapper à des propriétés. Le choix de la liaison GET convient pour les scénarios qui s’appuient sur des valeurs de routage ou de chaîne de requête.

Pour lier une propriété sur des requêtes GET, définissez la propriété SupportsGet de l’attribut [BindProperty] sur true :

[BindProperty(SupportsGet = true)]

Pour plus d’informations, consultez ASP.NET Core Community Standup: Bind on GET discussion (YouTube).

Mettez à jour la méthode OnGetAsync de la page Index avec le code suivant :

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 première ligne de la méthode OnGetAsync crée une requête LINQ pour sélectionner les films :

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

La requête est seulement définie à ce stade, elle n’a pas été exécutée sur la base de données.

Si la propriété SearchString n’est pas nulle ou vide, la requête sur les films est modifiée de façon à filtrer sur la chaîne de recherche :

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

Le code s => s.Title.Contains() est une expression lambda. Les expressions lambda sont utilisées dans les requêtes LINQ basées sur une méthode en tant qu’arguments pour les méthodes d’opérateur de requête standard, comme la méthode Where ou Contains. Les requêtes LINQ ne sont pas exécutées quand elles sont définies ou quand elles sont modifiées en appelant une méthode, comme Where, Contains ou OrderBy. Au lieu de cela, l’exécution de la requête est différée. L’évaluation d’une expression est retardée jusqu’à ce que sa valeur réalisée fasse l’objet d’une itération réelle ou que la méthode ToListAsync soit appelée. Pour plus d’informations, consultez Exécution de requête.

Remarque

La méthode Contains est exécutée sur la base de données, et non pas dans le code C#. Le respect de la casse pour la requête dépend de la base de données et du classement. Sur SQL Server, Contains est mappée à SQL LIKE, qui ne respecte pas la casse. SQLite avec le classement par défaut est un mélange de respect de la casse et de respect de la casse IN, en fonction de la requête. Pour plus d’informations sur la création de requêtes SQLite sans respect de la casse, consultez les rubriques suivantes :

Accédez à la page Films, puis ajoutez une chaîne de requête telle que ?searchString=Ghost à l’URL. Par exemple, https://localhost:5001/Movies?searchString=Ghost Les films filtrés sont affichés.

Vue Index

Si le modèle de routage suivant est ajouté à la page d’index, la chaîne de recherche peut être passée comme un segment d’URL. Par exemple, https://localhost:5001/Movies/Ghost

@page "{searchString?}"

La contrainte d’itinéraire précédente permet de rechercher le titre comme données d’itinéraire (un segment d’URL) et non comme valeur de chaîne de requête. Le ? dans "{searchString?}" signifie qu’il s’agit d’un paramètre d’itinéraire facultatif.

Vue Index avec le mot « ghost » ajouté à l’URL et une liste de films retournée contenant deux films, Ghostbusters et Ghostbusters 2

Le runtime ASP.NET Core utilise la liaison de modèle pour définir la valeur de la propriété SearchString à partir de la chaîne de requête (?searchString=Ghost) ou des données de la route (https://localhost:5001/Movies/Ghost). La liaison de modèle ne respecte pas la casse.

Cependant, vous ne pouvez pas attendre des utilisateurs qu’ils modifient l’URL pour rechercher un film. Dans cette étape, une interface utilisateur est ajoutée pour filtrer les films. Si vous avez ajouté la contrainte d’itinéraire "{searchString?}", supprimez-la.

Ouvrez le fichier Pages/Movies/Index.cshtml, puis ajoutez la balise mise en surbrillance dans le code suivant :

@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 balise HTML <form> utilise les Tag Helpers suivants :

  • Tag Helper Form. Quand le formulaire est envoyé, la chaîne de filtrage est envoyée à la page Pages/Movies/Index via la chaîne de requête.
  • Tag Helper Input

Enregistrez les modifications apportées, puis testez le filtre.

Vue Index avec le mot « ghost » tapé dans la zone de texte de filtre des titres

Rechercher par genre

Mettez à jour la méthode OnGetAsync de la page Index avec le code suivant :

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

Le code suivant est une requête LINQ qui récupère tous les genres dans la base de données.

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

La liste SelectList de genres est créée en projetant des différents genres.

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

Ajoutez une recherche par genre à la Page Razor

  1. Mettez à jour l'Index.cshtml <form> élément comme mis en évidence dans le balisage suivant :

    @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. Testez l’application en effectuant une recherche par genre, par titre de film et selon ces deux critères.

Étapes suivantes