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écessiteusing Microsoft.AspNetCore.Mvc.Rendering;
MovieGenre
: Contient le genre spécifique sélectionné par l’utilisateur. Par exemple, « Western ».Genres
etMovieGenre
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.
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.
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.
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 :
É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écessiteusing Microsoft.AspNetCore.Mvc.Rendering;
MovieGenre
: Contient le genre spécifique sélectionné par l’utilisateur. Par exemple, « Western ».Genres
etMovieGenre
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.
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.
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.
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écessiteusing Microsoft.AspNetCore.Mvc.Rendering;
MovieGenre
: Contient le genre spécifique sélectionné par l’utilisateur. Par exemple, « Western ».Genres
etMovieGenre
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.
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.
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.
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écessiteusing Microsoft.AspNetCore.Mvc.Rendering;
MovieGenre
: Contient le genre spécifique sélectionné par l’utilisateur. Par exemple, « Western ».Genres
etMovieGenre
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.
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.
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.
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écessiteusing Microsoft.AspNetCore.Mvc.Rendering;
MovieGenre
: Contient le genre spécifique sélectionné par l’utilisateur. Par exemple, « Western ».Genres
etMovieGenre
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.
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.
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.
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> <table class="table"> @*Markup removed for brevity.*@
Testez l’application en effectuant une recherche par genre, par titre de film et selon ces deux critères.