Parte 6, aggiungere la ricerca a ASP.NET Pagine principali Razor
Nota
Questa non è la versione più recente di questo articolo. Per la versione corrente, vedere la versione .NET 9 di questo articolo.
Avviso
Questa versione di ASP.NET Core non è più supportata. Per altre informazioni, vedere i criteri di supporto di .NET e .NET Core. Per la versione corrente, vedere la versione .NET 9 di questo articolo.
Importante
Queste informazioni si riferiscono a un prodotto non definitive che può essere modificato in modo sostanziale prima che venga rilasciato commercialmente. Microsoft non riconosce alcuna garanzia, espressa o implicita, in merito alle informazioni qui fornite.
Per la versione corrente, vedere la versione .NET 9 di questo articolo.
Nelle sezioni seguenti viene aggiunta la funzionalità di ricerca di film in base al genere oppure al nome.
Aggiungere il codice evidenziato seguente 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; }
Nel codice precedente:
SearchString
: contiene il testo immesso dagli utenti nella casella di testo di ricerca.SearchString
ha l'attributo[BindProperty]
.[BindProperty]
associa i valori modulo e le stringhe di query al nome della proprietà.[BindProperty(SupportsGet = true)]
è obbligatorio per l'associazione nelle richieste HTTP GET.Genres
: contiene l'elenco dei generi.Genres
consente all'utente di selezionare un genere dall'elenco.SelectList
richiedeusing Microsoft.AspNetCore.Mvc.Rendering;
MovieGenre
: contiene il genere specifico selezionato dall'utente. Ad esempio, "Western".Genres
eMovieGenre
sono utilizzati più avanti in questa esercitazione.
Avviso
Per motivi di sicurezza, è necessario acconsentire esplicitamente all'associazione dei dati della richiesta GET
alle proprietà del modello di pagina. Verificare l'input dell'utente prima di eseguirne il mapping alle proprietà. Acconsentire esplicitamente all'associazione GET
è utile in scenari basati su valori route o stringa di query.
Per associare una proprietà nelle richieste GET
, impostare la proprietà SupportsGet
dell'attributo [BindProperty]
su true
:
[BindProperty(SupportsGet = true)]
Per altre informazioni, vedere ASP.NET Core Community Standup: Bind on GET discussion (YouTube).
Aggiornare il Movies/Index
metodo della OnGetAsync
pagina con il codice seguente:
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 prima riga del metodo OnGetAsync
crea una query LINQ per selezionare i film:
var movies = from m in _context.Movie
select m;
La query viene solo definita in questo punto, ma non viene eseguita nel database.
Se la SearchString
proprietà non null
è o vuota, la query movies viene modificata per filtrare la stringa di ricerca:
if (!string.IsNullOrEmpty(SearchString))
{
movies = movies.Where(s => s.Title.Contains(SearchString));
}
Il codice s => s.Title.Contains()
è un'espressione lambda. Le espressioni lambda vengono usate nelle query LINQ basate su metodo come argomenti per metodi dell'operatore di query standard, ad esempio il metodo Where o Contains
. Le query LINQ non vengono eseguite quando vengono definite o quando vengono modificate chiamando un metodo, ad esempio Where
, Contains
o OrderBy
. L'esecuzione della query viene invece posticipata. La valutazione di un'espressione viene ritardata fino a quando non viene eseguito l'iterazione del relativo valore realizzato o viene chiamato il ToListAsync
metodo . Per altre informazioni, vedere Esecuzione di query.
Nota
Il Contains metodo viene eseguito nel database, non nel codice C#. La distinzione tra maiuscole/minuscole nella query dipende dal database e dalle regole di confronto. In SQL Server Contains
esegue il mapping a SQL LIKE che fa distinzione tra maiuscole e minuscole. SQLite con le regole di confronto predefinite è una combinazione di distinzione tra maiuscole e minuscole e di distinzione tra maiuscole e minuscole, a seconda della query. Per informazioni sull'esecuzione di query SQLite senza distinzione tra maiuscole e minuscole, vedere quanto segue:
Passare alla pagina Film e aggiungere una stringa di query, ?searchString=Ghost
ad esempio all'URL. Ad esempio: https://localhost:5001/Movies?searchString=Ghost
. Vengono visualizzati i film filtrati.
Se il modello di route seguente viene aggiunto alla pagina Indice, la stringa di ricerca può essere passata come segmento di URL. Ad esempio: https://localhost:5001/Movies/Ghost
.
@page "{searchString?}"
Il vincolo di route precedente consente la ricerca del titolo come dati della route (un segmento URL), anziché come valore della stringa di query. Il carattere ?
in "{searchString?}"
indica che questo parametro di route è facoltativo.
Il runtime di ASP.NET Core usa l'associazione di modelli per impostare il valore della proprietà SearchString
dalla stringa di query (?searchString=Ghost
) o dai dati della route (https://localhost:5001/Movies/Ghost
). L'associazione di modelli non fa distinzione tra maiuscole e minuscole.
Tuttavia, non è previsto che gli utenti modifichino l'URL per cercare un filmato. In questo passaggio viene aggiunta l'interfaccia utente per filtrare i film. Rimuovere il vincolo di route "{searchString?}"
, se è stato aggiunto.
Aprire il Pages/Movies/Index.cshtml
file e aggiungere il markup evidenziato nel codice seguente:
@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>
Il tag HTML <form>
usa gli helper tag seguenti:
- Helper tag Form. Quando il modulo viene inviato, la stringa di filtro verrà inviata alla pagina Pages/Movies/Index tramite una stringa di query.
- Helper per tag di input
Salvare le modifiche e testare il filtro.
Ricerca in base al genere
Aggiornare il Movies/Index.cshtml.cs
metodo page OnGetAsync
con il codice seguente:
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();
}
Il codice seguente è una query LINQ che recupera tutti i generi dal database.
IQueryable<string> genreQuery = from m in _context.Movie
orderby m.Genre
select m.Genre;
Il SelectList
di genere viene creato proiettando i generi distinti:
Genres = new SelectList(await genreQuery.Distinct().ToListAsync());
Aggiungere la ricerca per genere alla Razor pagina
Aggiornare l'elemento Index.cshtml
<form>
come evidenziato nel markup seguente:
@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>
Eseguire il test dell'app effettuando una ricerca per genere, titolo del film ed entrambi:
Passaggi successivi
Nelle sezioni seguenti viene aggiunta la funzionalità di ricerca di film in base al genere oppure al nome.
Aggiungere il codice evidenziato seguente 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; }
Nel codice precedente:
SearchString
: contiene il testo immesso dagli utenti nella casella di testo di ricerca.SearchString
ha l'attributo[BindProperty]
.[BindProperty]
associa i valori modulo e le stringhe di query al nome della proprietà.[BindProperty(SupportsGet = true)]
è obbligatorio per l'associazione nelle richieste HTTP GET.Genres
: contiene l'elenco dei generi.Genres
consente all'utente di selezionare un genere dall'elenco.SelectList
richiedeusing Microsoft.AspNetCore.Mvc.Rendering;
MovieGenre
: contiene il genere specifico selezionato dall'utente. Ad esempio, "Western".Genres
eMovieGenre
sono utilizzati più avanti in questa esercitazione.
Avviso
Per motivi di sicurezza, è necessario acconsentire esplicitamente all'associazione dei dati della richiesta GET
alle proprietà del modello di pagina. Verificare l'input dell'utente prima di eseguirne il mapping alle proprietà. Acconsentire esplicitamente all'associazione GET
è utile in scenari basati su valori route o stringa di query.
Per associare una proprietà nelle richieste GET
, impostare la proprietà SupportsGet
dell'attributo [BindProperty]
su true
:
[BindProperty(SupportsGet = true)]
Per altre informazioni, vedere ASP.NET Core Community Standup: Bind on GET discussion (YouTube).
Aggiornare il metodo OnGetAsync
della pagina di indice con il codice seguente:
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 prima riga del metodo OnGetAsync
crea una query LINQ per selezionare i film:
// using System.Linq;
var movies = from m in _context.Movie
select m;
La query viene solo definita in questo punto, ma non viene eseguita nel database.
Se la SearchString
proprietà non null
è o vuota, la query movies viene modificata per filtrare la stringa di ricerca:
if (!string.IsNullOrEmpty(SearchString))
{
movies = movies.Where(s => s.Title.Contains(SearchString));
}
Il codice s => s.Title.Contains()
è un'espressione lambda. Le espressioni lambda vengono usate nelle query LINQ basate su metodo come argomenti per metodi dell'operatore di query standard, ad esempio il metodo Where o Contains
. Le query LINQ non vengono eseguite quando vengono definite o quando vengono modificate chiamando un metodo, ad esempio Where
, Contains
o OrderBy
. L'esecuzione della query viene invece posticipata. La valutazione di un'espressione viene ritardata fino a quando non viene eseguito l'iterazione del relativo valore realizzato o viene chiamato il ToListAsync
metodo . Per altre informazioni, vedere Esecuzione di query.
Nota
Il Contains metodo viene eseguito nel database, non nel codice C#. La distinzione tra maiuscole/minuscole nella query dipende dal database e dalle regole di confronto. In SQL Server Contains
esegue il mapping a SQL LIKE che fa distinzione tra maiuscole e minuscole. SQLite con le regole di confronto predefinite è una combinazione di distinzione tra maiuscole e minuscole e di distinzione tra maiuscole e minuscole, a seconda della query. Per informazioni sull'esecuzione di query SQLite senza distinzione tra maiuscole e minuscole, vedere quanto segue:
Passare alla pagina Film e aggiungere una stringa di query, ?searchString=Ghost
ad esempio all'URL. Ad esempio: https://localhost:5001/Movies?searchString=Ghost
. Vengono visualizzati i film filtrati.
Se il modello di route seguente viene aggiunto alla pagina Indice, la stringa di ricerca può essere passata come segmento di URL. Ad esempio: https://localhost:5001/Movies/Ghost
.
@page "{searchString?}"
Il vincolo di route precedente consente la ricerca del titolo come dati della route (un segmento URL), anziché come valore della stringa di query. Il carattere ?
in "{searchString?}"
indica che questo parametro di route è facoltativo.
Il runtime di ASP.NET Core usa l'associazione di modelli per impostare il valore della proprietà SearchString
dalla stringa di query (?searchString=Ghost
) o dai dati della route (https://localhost:5001/Movies/Ghost
). L'associazione di modelli non fa distinzione tra maiuscole e minuscole.
Tuttavia, non è previsto che gli utenti modifichino l'URL per cercare un filmato. In questo passaggio viene aggiunta l'interfaccia utente per filtrare i film. Rimuovere il vincolo di route "{searchString?}"
, se è stato aggiunto.
Aprire il Pages/Movies/Index.cshtml
file e aggiungere il markup evidenziato nel codice seguente:
@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.*@
Il tag HTML <form>
usa gli helper tag seguenti:
- Helper tag Form. Quando il modulo viene inviato, la stringa di filtro verrà inviata alla pagina Pages/Movies/Index tramite una stringa di query.
- Helper per tag di input
Salvare le modifiche e testare il filtro.
Ricerca in base al genere
Aggiornare il Movies/Index.cshtml.cs
metodo page OnGetAsync
con il codice seguente:
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();
}
Il codice seguente è una query LINQ che recupera tutti i generi dal database.
// Use LINQ to get list of genres.
IQueryable<string> genreQuery = from m in _context.Movie
orderby m.Genre
select m.Genre;
L'elenco SelectList
di generi viene creato selezionando generi distinti.
Genres = new SelectList(await genreQuery.Distinct().ToListAsync());
Aggiungere la ricerca per genere alla Razor pagina
Aggiornare l'elemento Index.cshtml
<form>
come evidenziato nel markup seguente:
@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>
Eseguire il test dell'app effettuando una ricerca per genere, titolo del film e usando entrambi i filtri.
Passaggi successivi
Nelle sezioni seguenti viene aggiunta la funzionalità di ricerca di film in base al genere oppure al nome.
Aggiungere il codice evidenziato seguente 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; }
Nel codice precedente:
SearchString
: contiene il testo immesso dagli utenti nella casella di testo di ricerca.SearchString
ha l'attributo[BindProperty]
.[BindProperty]
associa i valori modulo e le stringhe di query al nome della proprietà.[BindProperty(SupportsGet = true)]
è obbligatorio per l'associazione nelle richieste HTTP GET.Genres
: contiene l'elenco dei generi.Genres
consente all'utente di selezionare un genere dall'elenco.SelectList
richiedeusing Microsoft.AspNetCore.Mvc.Rendering;
MovieGenre
: contiene il genere specifico selezionato dall'utente. Ad esempio, "Western".Genres
eMovieGenre
sono utilizzati più avanti in questa esercitazione.
Avviso
Per motivi di sicurezza, è necessario acconsentire esplicitamente all'associazione dei dati della richiesta GET
alle proprietà del modello di pagina. Verificare l'input dell'utente prima di eseguirne il mapping alle proprietà. Acconsentire esplicitamente all'associazione GET
è utile in scenari basati su valori route o stringa di query.
Per associare una proprietà nelle richieste GET
, impostare la proprietà SupportsGet
dell'attributo [BindProperty]
su true
:
[BindProperty(SupportsGet = true)]
Per altre informazioni, vedere ASP.NET Core Community Standup: Bind on GET discussion (YouTube).
Aggiornare il metodo OnGetAsync
della pagina di indice con il codice seguente:
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 prima riga del metodo OnGetAsync
crea una query LINQ per selezionare i film:
// using System.Linq;
var movies = from m in _context.Movie
select m;
La query viene solo definita in questo punto, ma non viene eseguita nel database.
Se la SearchString
proprietà non null
è o vuota, la query movies viene modificata per filtrare la stringa di ricerca:
if (!string.IsNullOrEmpty(SearchString))
{
movies = movies.Where(s => s.Title.Contains(SearchString));
}
Il codice s => s.Title.Contains()
è un'espressione lambda. Le espressioni lambda vengono usate nelle query LINQ basate su metodo come argomenti per metodi dell'operatore di query standard, ad esempio il metodo Where o Contains
. Le query LINQ non vengono eseguite quando vengono definite o quando vengono modificate chiamando un metodo, ad esempio Where
, Contains
o OrderBy
. L'esecuzione della query viene invece posticipata. La valutazione di un'espressione viene ritardata fino a quando non viene eseguito l'iterazione del relativo valore realizzato o viene chiamato il ToListAsync
metodo . Per altre informazioni, vedere Esecuzione di query.
Nota
Il Contains metodo viene eseguito nel database, non nel codice C#. La distinzione tra maiuscole/minuscole nella query dipende dal database e dalle regole di confronto. In SQL Server Contains
esegue il mapping a SQL LIKE che fa distinzione tra maiuscole e minuscole. SQLite con le regole di confronto predefinite è una combinazione di distinzione tra maiuscole e minuscole e di distinzione tra maiuscole e minuscole, a seconda della query. Per informazioni sull'esecuzione di query SQLite senza distinzione tra maiuscole e minuscole, vedere quanto segue:
- Questo problema di GitHub
- Questo problema di GitHub
- Regole di confronto e distinzione tra maiuscole e minuscole
Passare alla pagina Film e aggiungere una stringa di query, ?searchString=Ghost
ad esempio all'URL. Ad esempio: https://localhost:5001/Movies?searchString=Ghost
. Vengono visualizzati i film filtrati.
Se il modello di route seguente viene aggiunto alla pagina Indice, la stringa di ricerca può essere passata come segmento di URL. Ad esempio: https://localhost:5001/Movies/Ghost
.
@page "{searchString?}"
Il vincolo di route precedente consente la ricerca del titolo come dati della route (un segmento URL), anziché come valore della stringa di query. Il carattere ?
in "{searchString?}"
indica che questo parametro di route è facoltativo.
Il runtime di ASP.NET Core usa l'associazione di modelli per impostare il valore della proprietà SearchString
dalla stringa di query (?searchString=Ghost
) o dai dati della route (https://localhost:5001/Movies/Ghost
). L'associazione di modelli non fa distinzione tra maiuscole e minuscole.
Tuttavia, non è previsto che gli utenti modifichino l'URL per cercare un filmato. In questo passaggio viene aggiunta l'interfaccia utente per filtrare i film. Rimuovere il vincolo di route "{searchString?}"
, se è stato aggiunto.
Aprire il Pages/Movies/Index.cshtml
file e aggiungere il markup evidenziato nel codice seguente:
@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.*@
Il tag HTML <form>
usa gli helper tag seguenti:
- Helper tag Form. Quando il modulo viene inviato, la stringa di filtro verrà inviata alla pagina Pages/Movies/Index tramite una stringa di query.
- Helper per tag di input
Salvare le modifiche e testare il filtro.
Ricerca in base al genere
Aggiornare il metodo OnGetAsync
della pagina di indice con il codice seguente:
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();
}
Il codice seguente è una query LINQ che recupera tutti i generi dal database.
// Use LINQ to get list of genres.
IQueryable<string> genreQuery = from m in _context.Movie
orderby m.Genre
select m.Genre;
L'elenco SelectList
di generi viene creato selezionando generi distinti.
Genres = new SelectList(await genreQuery.Distinct().ToListAsync());
Aggiungere la ricerca per genere alla Razor pagina
Aggiornare l'elemento Index.cshtml
<form>
come evidenziato nel markup seguente:
@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>
Eseguire il test dell'app effettuando una ricerca per genere, titolo del film e usando entrambi i filtri.
Passaggi successivi
Nelle sezioni seguenti viene aggiunta la funzionalità di ricerca di film in base al genere oppure al nome.
Aggiungere il codice evidenziato seguente 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; }
Nel codice precedente:
SearchString
: contiene il testo immesso dagli utenti nella casella di testo di ricerca.SearchString
ha l'attributo[BindProperty]
.[BindProperty]
associa i valori modulo e le stringhe di query al nome della proprietà.[BindProperty(SupportsGet = true)]
è obbligatorio per l'associazione nelle richieste HTTP GET.Genres
: contiene l'elenco dei generi.Genres
consente all'utente di selezionare un genere dall'elenco.SelectList
richiedeusing Microsoft.AspNetCore.Mvc.Rendering;
MovieGenre
: contiene il genere specifico selezionato dall'utente. Ad esempio, "Western".Genres
eMovieGenre
sono utilizzati più avanti in questa esercitazione.
Avviso
Per motivi di sicurezza, è necessario acconsentire esplicitamente all'associazione dei dati della richiesta GET
alle proprietà del modello di pagina. Verificare l'input dell'utente prima di eseguirne il mapping alle proprietà. Acconsentire esplicitamente all'associazione GET
è utile in scenari basati su valori route o stringa di query.
Per associare una proprietà nelle richieste GET
, impostare la proprietà SupportsGet
dell'attributo [BindProperty]
su true
:
[BindProperty(SupportsGet = true)]
Per altre informazioni, vedere ASP.NET Core Community Standup: Bind on GET discussion (YouTube).
Aggiornare il metodo OnGetAsync
della pagina di indice con il codice seguente:
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 prima riga del metodo OnGetAsync
crea una query LINQ per selezionare i film:
// using System.Linq;
var movies = from m in _context.Movie
select m;
La query viene solo definita in questo punto, ma non viene eseguita nel database.
Se la proprietà SearchString
non è null o vuota, la query dei film viene modificata per filtrare gli elementi in base alla stringa di ricerca:
if (!string.IsNullOrEmpty(SearchString))
{
movies = movies.Where(s => s.Title.Contains(SearchString));
}
Il codice s => s.Title.Contains()
è un'espressione lambda. Le espressioni lambda vengono usate nelle query LINQ basate su metodo come argomenti per metodi dell'operatore di query standard, ad esempio il metodo Where o Contains
. Le query LINQ non vengono eseguite quando vengono definite o quando vengono modificate chiamando un metodo, ad esempio Where
, Contains
o OrderBy
. L'esecuzione della query viene invece posticipata. La valutazione di un'espressione viene ritardata fino a quando non viene eseguito l'iterazione del relativo valore realizzato o viene chiamato il ToListAsync
metodo . Per altre informazioni, vedere Esecuzione di query.
Nota
Il Contains metodo viene eseguito nel database, non nel codice C#. La distinzione tra maiuscole/minuscole nella query dipende dal database e dalle regole di confronto. In SQL Server Contains
esegue il mapping a SQL LIKE che fa distinzione tra maiuscole e minuscole. SQLite con le regole di confronto predefinite è una combinazione di distinzione tra maiuscole e minuscole e di distinzione tra maiuscole e minuscole, a seconda della query. Per informazioni sull'esecuzione di query SQLite senza distinzione tra maiuscole e minuscole, vedere quanto segue:
- Questo problema di GitHub
- Questo problema di GitHub
- Regole di confronto e distinzione tra maiuscole e minuscole
Passare alla pagina Film e aggiungere una stringa di query, ?searchString=Ghost
ad esempio all'URL. Ad esempio: https://localhost:5001/Movies?searchString=Ghost
. Vengono visualizzati i film filtrati.
Se il modello di route seguente viene aggiunto alla pagina Indice, la stringa di ricerca può essere passata come segmento di URL. Ad esempio: https://localhost:5001/Movies/Ghost
.
@page "{searchString?}"
Il vincolo di route precedente consente la ricerca del titolo come dati della route (un segmento URL), anziché come valore della stringa di query. Il carattere ?
in "{searchString?}"
indica che questo parametro di route è facoltativo.
Il runtime di ASP.NET Core usa l'associazione di modelli per impostare il valore della proprietà SearchString
dalla stringa di query (?searchString=Ghost
) o dai dati della route (https://localhost:5001/Movies/Ghost
). L'associazione di modelli non fa distinzione tra maiuscole e minuscole.
Tuttavia, non è previsto che gli utenti modifichino l'URL per cercare un filmato. In questo passaggio viene aggiunta l'interfaccia utente per filtrare i film. Rimuovere il vincolo di route "{searchString?}"
, se è stato aggiunto.
Aprire il Pages/Movies/Index.cshtml
file e aggiungere il markup evidenziato nel codice seguente:
@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.*@
Il tag HTML <form>
usa gli helper tag seguenti:
- Helper tag Form. Quando il modulo viene inviato, la stringa di filtro verrà inviata alla pagina Pages/Movies/Index tramite una stringa di query.
- Helper per tag di input
Salvare le modifiche e testare il filtro.
Ricerca in base al genere
Aggiornare il metodo OnGetAsync
della pagina di indice con il codice seguente:
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();
}
Il codice seguente è una query LINQ che recupera tutti i generi dal database.
// Use LINQ to get list of genres.
IQueryable<string> genreQuery = from m in _context.Movie
orderby m.Genre
select m.Genre;
L'elenco SelectList
di generi viene creato selezionando generi distinti.
Genres = new SelectList(await genreQuery.Distinct().ToListAsync());
Aggiungere la ricerca per genere alla Razor pagina
Aggiornare l'elemento Index.cshtml
<form>
come evidenziato nel markup seguente:
@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>
Eseguire il test dell'app effettuando una ricerca per genere, titolo del film e usando entrambi i filtri.
Passaggi successivi
Nelle sezioni seguenti viene aggiunta la funzionalità di ricerca di film in base al genere oppure al nome.
Aggiungere le proprietà e l'istruzione using seguenti evidenziate 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; }
Nel codice precedente:
SearchString
: contiene il testo immesso dagli utenti nella casella di testo di ricerca.SearchString
ha l'attributo[BindProperty]
.[BindProperty]
associa i valori modulo e le stringhe di query al nome della proprietà.[BindProperty(SupportsGet = true)]
è obbligatorio per l'associazione nelle richieste HTTP GET.Genres
: contiene l'elenco dei generi.Genres
consente all'utente di selezionare un genere dall'elenco.SelectList
richiedeusing Microsoft.AspNetCore.Mvc.Rendering;
MovieGenre
: contiene il genere specifico selezionato dall'utente. Ad esempio, "Western".Genres
eMovieGenre
sono utilizzati più avanti in questa esercitazione.
Avviso
Per motivi di sicurezza, è necessario acconsentire esplicitamente all'associazione dei dati della richiesta GET
alle proprietà del modello di pagina. Verificare l'input dell'utente prima di eseguirne il mapping alle proprietà. Acconsentire esplicitamente all'associazione GET
è utile in scenari basati su valori route o stringa di query.
Per associare una proprietà nelle richieste GET
, impostare la proprietà SupportsGet
dell'attributo [BindProperty]
su true
:
[BindProperty(SupportsGet = true)]
Per altre informazioni, vedere ASP.NET Core Community Standup: Bind on GET discussion (YouTube).
Aggiornare il metodo OnGetAsync
della pagina di indice con il codice seguente:
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 prima riga del metodo OnGetAsync
crea una query LINQ per selezionare i film:
// using System.Linq;
var movies = from m in _context.Movie
select m;
La query viene solo definita in questo punto, ma non viene eseguita nel database.
Se la proprietà SearchString
non è null o vuota, la query dei film viene modificata per filtrare gli elementi in base alla stringa di ricerca:
if (!string.IsNullOrEmpty(SearchString))
{
movies = movies.Where(s => s.Title.Contains(SearchString));
}
Il codice s => s.Title.Contains()
è un'espressione lambda. Le espressioni lambda vengono usate nelle query LINQ basate su metodo come argomenti per metodi dell'operatore di query standard, ad esempio il metodo Where o Contains
. Le query LINQ non vengono eseguite quando vengono definite o quando vengono modificate chiamando un metodo, ad esempio Where
, Contains
o OrderBy
. L'esecuzione della query viene invece posticipata. La valutazione di un'espressione viene ritardata fino a quando non viene eseguito l'iterazione del relativo valore realizzato o viene chiamato il ToListAsync
metodo . Per altre informazioni, vedere Esecuzione di query.
Nota
Il Contains metodo viene eseguito nel database, non nel codice C#. La distinzione tra maiuscole/minuscole nella query dipende dal database e dalle regole di confronto. In SQL Server Contains
esegue il mapping a SQL LIKE che fa distinzione tra maiuscole e minuscole. SQLite con le regole di confronto predefinite è una combinazione di distinzione tra maiuscole e minuscole e di distinzione tra maiuscole e minuscole, a seconda della query. Per informazioni sull'esecuzione di query SQLite senza distinzione tra maiuscole e minuscole, vedere quanto segue:
- Questo problema di GitHub.
- Questo problema di GitHub
- Regole di confronto e distinzione tra maiuscole e minuscole
Passare alla pagina Film e aggiungere una stringa di query, ?searchString=Ghost
ad esempio all'URL. Ad esempio: https://localhost:5001/Movies?searchString=Ghost
. Vengono visualizzati i film filtrati.
Se il modello di route seguente viene aggiunto alla pagina Indice, la stringa di ricerca può essere passata come segmento di URL. Ad esempio: https://localhost:5001/Movies/Ghost
.
@page "{searchString?}"
Il vincolo di route precedente consente la ricerca del titolo come dati della route (un segmento URL), anziché come valore della stringa di query. Il carattere ?
in "{searchString?}"
indica che questo parametro di route è facoltativo.
Il runtime di ASP.NET Core usa l'associazione di modelli per impostare il valore della proprietà SearchString
dalla stringa di query (?searchString=Ghost
) o dai dati della route (https://localhost:5001/Movies/Ghost
). L'associazione di modelli non fa distinzione tra maiuscole e minuscole.
Tuttavia, non è previsto che gli utenti modifichino l'URL per cercare un filmato. In questo passaggio viene aggiunta l'interfaccia utente per filtrare i film. Rimuovere il vincolo di route "{searchString?}"
, se è stato aggiunto.
Aprire il Pages/Movies/Index.cshtml
file e aggiungere il markup evidenziato nel codice seguente:
@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.*@
Il tag HTML <form>
usa gli helper tag seguenti:
- Helper tag Form. Quando il modulo viene inviato, la stringa di filtro verrà inviata alla pagina Pages/Movies/Index tramite una stringa di query.
- Helper per tag di input
Salvare le modifiche e testare il filtro.
Ricerca in base al genere
Aggiornare il metodo OnGetAsync
della pagina di indice con il codice seguente:
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();
}
Il codice seguente è una query LINQ che recupera tutti i generi dal database.
// Use LINQ to get list of genres.
IQueryable<string> genreQuery = from m in _context.Movie
orderby m.Genre
select m.Genre;
L'elenco SelectList
di generi viene creato selezionando generi distinti.
Genres = new SelectList(await genreQuery.Distinct().ToListAsync());
Aggiungere la ricerca per genere alla Razor pagina
Aggiornare l'elemento
Index.cshtml
<form>
come evidenziato nel markup seguente:@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.*@
Eseguire il test dell'app effettuando una ricerca per genere, titolo del film e usando entrambi i filtri.