Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
Jegyzet
Ez nem a cikk legújabb verziója. Az aktuális kiadásról a cikk .NET 10-es verziójában olvashat.
Figyelmeztetés
A ASP.NET Core ezen verziója már nem támogatott. További információ: .NET és .NET Core támogatási szabályzat. Az aktuális kiadást a jelen cikk .NET 9-es verziójában.
Készítette: Rick Anderson
Ebben a szakaszban keresési funkciót ad hozzá a Index műveletmetódushoz, amely lehetővé teszi a filmek keresését műfaji vagy névalapján.
Frissítse a Index metódust, amely a Controllers/MoviesController.cs-ben található, a következő kóddal:
public async Task<IActionResult> Index(string searchString)
{
if (_context.Movie == null)
{
return Problem("Entity set 'MvcMovieContext.Movie' is null.");
}
var movies = from m in _context.Movie
select m;
if (!String.IsNullOrEmpty(searchString))
{
movies = movies.Where(s => s.Title!.ToUpper().Contains(searchString.ToUpper()));
}
return View(await movies.ToListAsync());
}
A Index műveletmetódus következő sora létrehoz egy LINQ lekérdezést a filmek kiválasztásához:
var movies = from m in _context.Movie
select m;
A lekérdezés jelenleg csak van definiálva; még nem lett futtatva az adatbázison.
Ha a searchString paraméter tartalmaz egy sztringet, a rendszer úgy módosítja a mozgókép-lekérdezést, hogy a keresési sztring értékére szűrjön:
if (!String.IsNullOrEmpty(searchString))
{
movies = movies.Where(s => s.Title!.ToUpper().Contains(searchString.ToUpper()));
}
A fenti s => s.Title!.ToUpper().Contains(searchString.ToUpper()) kód egy Lambda Expression. A lambdákat a metódusalapú LINQ lekérdezésekben használják a standard lekérdezési operátor metódusok, mint például a Where metódus vagy a Contains (használva a fenti kódban), argumentumaként. A LINQ-lekérdezések nem lesznek végrehajtva, amikor definiálják őket, vagy ha módosítják őket egy olyan metódus meghívásával, mint például Where, Containsvagy OrderBy. Ehelyett a lekérdezések végrehajtása halasztva van. Ez azt jelenti, hogy egy kifejezés kiértékelése késleltetve van, amíg a realizált értéket ténylegesen végig nem iterálják, vagy amíg a ToListAsync metódust meg nem hívják. További információ a halasztott lekérdezések végrehajtásáról: Lekérdezés végrehajtása.
Jegyzet
A Contains metódus az adatbázisban fut, nem a C# kódban. A lekérdezés kis- és nagybetűk érzékenysége az adatbázistól és a kollációtól függ. Az SQL Serveren a Contains a SQL LIKEértékre képezhető le, ami nem érzékeny a kis- és nagybetűkre. Az alapértelmezett rendezéssel rendelkező SQLite esetében a kis- és nagybetű érzékenység keveredik, az éppen használt lekérdezéstől függően. IN Az esetérzékeny SQLite-lekérdezések készítésével kapcsolatos információkért tekintse meg a következőket:
Irányítson a /Movies/Index-ra. Adjon hozzá egy lekérdezési sztringet, például ?searchString=Ghost az URL-címhez. A szűrt filmek megjelennek.
Ha úgy módosítja a Index metódus aláírását, hogy egy idnevű paraméterrel rendelkezzen, a id paraméter megfelel az {id}alapértelmezett útvonalainak választható Program.cs helyőrzőjének.
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
Módosítsa a paraméter értékét id-ra, és módosítsa a searchString összes előfordulását id-re.
Az előző Index metódus:
public async Task<IActionResult> Index(string searchString)
{
if (_context.Movie == null)
{
return Problem("Entity set 'MvcMovieContext.Movie' is null.");
}
var movies = from m in _context.Movie
select m;
if (!String.IsNullOrEmpty(searchString))
{
movies = movies.Where(s => s.Title!.ToUpper().Contains(searchString.ToUpper()));
}
return View(await movies.ToListAsync());
}
A frissített Index metódus id paraméterrel:
public async Task<IActionResult> Index(string id)
{
if (_context.Movie == null)
{
return Problem("Entity set 'MvcMovieContext.Movie' is null.");
}
var movies = from m in _context.Movie
select m;
if (!String.IsNullOrEmpty(id))
{
movies = movies.Where(s => s.Title!.ToUpper().Contains(id.ToUpper()));
}
return View(await movies.ToListAsync());
}
A keresési címet mostantól útvonaladatként (URL-szegmensként) is átadhatja lekérdezési sztringérték helyett.
Azonban nem számíthat arra, hogy a felhasználók minden alkalommal módosítják az URL-címet, amikor filmet szeretnének keresni. Így most felhasználói felületi elemeket fog hozzáadni, hogy segítsen nekik a filmek szűrésében. Ha módosította a Index metódus aláírását az útvonalhoz kötött ID paraméter átadásának teszteléséhez, módosítsa vissza, hogy egy searchStringnevű paramétert használjon:
public async Task<IActionResult> Index(string searchString)
{
if (_context.Movie == null)
{
return Problem("Entity set 'MvcMovieContext.Movie' is null.");
}
var movies = from m in _context.Movie
select m;
if (!String.IsNullOrEmpty(searchString))
{
movies = movies.Where(s => s.Title!.ToUpper().Contains(searchString.ToUpper()));
}
return View(await movies.ToListAsync());
}
Nyissa meg a Views/Movies/Index.cshtml fájlt, és adja hozzá az alább kiemelt <form> jelölést:
@model IEnumerable<MvcMovie.Models.Movie>
@{
ViewData["Title"] = "Index";
}
<h1>Index</h1>
<p>
<a asp-action="Create">Create New</a>
</p>
<form asp-controller="Movies" asp-action="Index">
<p>
<label>Title: <input type="text" name="SearchString" /></label>
<input type="submit" value="Filter" />
</p>
</form>
<table class="table">
A HTML-<form> címke az űrlapcímke-segéd-t használja, így az űrlap feladásakor a szűrő karakterlánc a filmvezérlő Index művelethez kerül továbbításra. Mentse a módosításokat, majd tesztelje a szűrőt.
A [HttpPost] metódusnak nincs Index túlterhelése, ahogy várható. Nincs rá szükség, mert a metódus nem módosítja az alkalmazás állapotát, csak szűri az adatokat.
A következő [HttpPost] Index metódust adhatja hozzá.
[HttpPost]
public string Index(string searchString, bool notUsed)
{
return "From [HttpPost]Index: filter on " + searchString;
}
A notUsed paraméter a Index metódus túlterhelésének létrehozására szolgál. Erről az oktatóanyag későbbi részében lesz szó.
Ha hozzáadja ezt a metódust, a műveletindító megfelel a [HttpPost] Index metódusnak, és a [HttpPost] Index metódus az alábbi képen látható módon fut.
Azonban még akkor is, ha hozzáadja a [HttpPost] metódus ezen Index verzióját, van egy korlátozás abban, ahogyan mindez megvalósításra került. Tegyük fel, hogy egy adott keresést szeretne könyvjelzővel megjelölni, vagy egy olyan hivatkozást szeretne küldeni barátainak, amelyekre kattintva megtekintheti a filmek szűrt listáját. Figyelje meg, hogy a HTTP POST-kérelem URL-címe megegyezik a GET-kérés URL-címével (localhost:{PORT}/Movies/Index) – az URL-címben nincs keresési információ. A keresési sztring adatait a rendszer űrlapmező-értékként küldi el a kiszolgálónak. Ellenőrizheti a böngésző fejlesztői eszközeinek vagy a kiváló Fiddler eszköznek a segítségével.
Az alábbi képen a Chrome böngésző fejlesztői eszközei láthatók a Hálózati és Fejlécek lapok kiválasztva.
searchString értékével
A Hálózat és a Terhelési fülek vannak kiválasztva az űrlapadatok megtekintéséhez:
A keresési paraméter és a XSRF token a kérelem törzsében látható. Vegye figyelembe, hogy az előző oktatóanyagban említett módon az űrlappéldány-segítő létrehoz egy XSRF hamisítás elleni tokent. Nem módosítjuk az adatokat, ezért nem kell érvényesítenünk a jogkivonatot a vezérlőmetódusban.
Mivel a keresési paraméter nem az URL-cím, hanem a kérelem törzsében található, ezeket a keresési adatokat nem rögzítheti könyvjelzőként vagy másokkal való megosztáshoz. Úgy javíthatja ki ezt, hogy megadja, a kérés legyen HTTP GET a form címkében, amely a Views/Movies/Index.cshtml fájlban található.
@model IEnumerable<MvcMovie.Models.Movie>
@{
ViewData["Title"] = "Index";
}
<h1>Index</h1>
<p>
<a asp-action="Create">Create New</a>
</p>
<form asp-controller="Movies" asp-action="Index" method="get">
<p>
<label>Title: <input type="text" name="SearchString" /></label>
<input type="submit" value="Filter" />
</p>
</form>
<table class="table">
Most, amikor elküld egy keresést, az URL-cím tartalmazza a keresési lekérdezési sztringet. A keresés a HttpGet Index műveletmetódusra is vonatkozik, még akkor is, ha rendelkezik HttpPost Index metódussal.
Keresés hozzáadása műfaj szerint
Adja hozzá a következő MovieGenreViewModel osztályt a Modellek mappához:
using Microsoft.AspNetCore.Mvc.Rendering;
using System.Collections.Generic;
namespace MvcMovie.Models;
public class MovieGenreViewModel
{
public List<Movie>? Movies { get; set; }
public SelectList? Genres { get; set; }
public string? MovieGenre { get; set; }
public string? SearchString { get; set; }
}
A film-műfaj nézetmodell a következőket tartalmazza:
- A filmek listája.
- A műfajok listáját tartalmazó
SelectList. Így a felhasználó kiválaszthat egy műfajt a listából. -
MovieGenre, amely a kiválasztott műfajt tartalmazza. -
SearchString, amely a keresőmezőbe beírt szöveget tartalmazza.
Cserélje le a Index metódust a MoviesController.cs-ban/-ben a következő kódra:
// GET: Movies
public async Task<IActionResult> Index(string movieGenre, string searchString)
{
if (_context.Movie == null)
{
return Problem("Entity set 'MvcMovieContext.Movie' is null.");
}
// 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!.ToUpper().Contains(searchString.ToUpper()));
}
if (!string.IsNullOrEmpty(movieGenre))
{
movies = movies.Where(x => x.Genre == movieGenre);
}
var movieGenreVM = new MovieGenreViewModel
{
Genres = new SelectList(await genreQuery.Distinct().ToListAsync()),
Movies = await movies.ToListAsync()
};
return View(movieGenreVM);
}
Az alábbi kód egy LINQ lekérdezés, amely lekéri az összes műfajt az adatbázisból.
// Use LINQ to get list of genres.
IQueryable<string> genreQuery = from m in _context.Movie
orderby m.Genre
select m.Genre;
A műfajok SelectList a különböző műfajok kivetítésével jön létre (nem szeretnénk, hogy a kiválasztási lista duplikált műfajokkal rendelkezzen).
Amikor a felhasználó megkeresi az elemet, a keresési érték megmarad a keresőmezőben.
Keresés hozzáadása műfaj szerint az Index nézethez
A Index.cshtml frissítése megtalálható a Nézetek/Filmek/ alatt az alábbiak szerint:
@model MvcMovie.Models.MovieGenreViewModel
@{
ViewData["Title"] = "Index";
}
<h1>Index</h1>
<p>
<a asp-action="Create">Create New</a>
</p>
<form asp-controller="Movies" asp-action="Index" method="get">
<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">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Movies![0].Title)
</th>
<th>
@Html.DisplayNameFor(model => model.Movies![0].ReleaseDate)
</th>
<th>
@Html.DisplayNameFor(model => model.Movies![0].Genre)
</th>
<th>
@Html.DisplayNameFor(model => model.Movies![0].Price)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.Movies!)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.ReleaseDate)
</td>
<td>
@Html.DisplayFor(modelItem => item.Genre)
</td>
<td>
@Html.DisplayFor(modelItem => item.Price)
</td>
<td>
<a asp-action="Edit" asp-route-id="@item.Id">Edit</a> |
<a asp-action="Details" asp-route-id="@item.Id">Details</a> |
<a asp-action="Delete" asp-route-id="@item.Id">Delete</a>
</td>
</tr>
}
</tbody>
</table>
Vizsgálja meg a következő HTML-segédben használt lambda kifejezést:
@Html.DisplayNameFor(model => model.Movies![0].Title)
Az előző kódban a DisplayNameFor HTML-segéd a lambda kifejezésben hivatkozott Title tulajdonságot vizsgálja a megjelenítendő név meghatározásához. Mivel a lambda kifejezést nem kiértékelik, nem kap hozzáférési szabálysértést, ha model, model.Moviesvagy model.Movies[0]null vagy üres. A lambda kifejezés kiértékelésekor (például @Html.DisplayFor(modelItem => item.Title)) a modell tulajdonságértékei lesznek kiértékelve. A ! utáni model.Movies a null-megbocsátó operátor, amelyet annak deklarálására használnak, hogy a Movies nem nulla.
Tesztelje az alkalmazást műfaj, filmcím és mindkettő alapján:
Ebben a szakaszban keresési funkciót ad hozzá a Index műveletmetódushoz, amely lehetővé teszi a filmek keresését műfaji vagy névalapján.
Frissítse a Index metódust, amely a Controllers/MoviesController.cs-ben található, a következő kóddal:
public async Task<IActionResult> Index(string searchString)
{
if (_context.Movie == null)
{
return Problem("Entity set 'MvcMovieContext.Movie' is null.");
}
var movies = from m in _context.Movie
select m;
if (!String.IsNullOrEmpty(searchString))
{
movies = movies.Where(s => s.Title!.ToUpper().Contains(searchString.ToUpper()));
}
return View(await movies.ToListAsync());
}
A Index műveletmetódus következő sora létrehoz egy LINQ lekérdezést a filmek kiválasztásához:
var movies = from m in _context.Movie
select m;
A lekérdezés jelenleg csak van definiálva; még nem lett futtatva az adatbázison.
Ha a searchString paraméter tartalmaz egy sztringet, a rendszer úgy módosítja a mozgókép-lekérdezést, hogy a keresési sztring értékére szűrjön:
if (!String.IsNullOrEmpty(searchString))
{
movies = movies.Where(s => s.Title!.ToUpper().Contains(searchString.ToUpper()));
}
A fenti s => s.Title!.ToUpper().Contains(searchString.ToUpper()) kód egy Lambda Expression. A lambdákat a metódusalapú LINQ lekérdezésekben használják a standard lekérdezési operátor metódusok, mint például a Where metódus vagy a Contains (használva a fenti kódban), argumentumaként. A LINQ-lekérdezések nem lesznek végrehajtva, amikor definiálják őket, vagy ha módosítják őket egy olyan metódus meghívásával, mint például Where, Containsvagy OrderBy. Ehelyett a lekérdezések végrehajtása halasztva van. Ez azt jelenti, hogy egy kifejezés kiértékelése késleltetve van, amíg a realizált értéket ténylegesen végig nem iterálják, vagy amíg a ToListAsync metódust meg nem hívják. További információ a halasztott lekérdezések végrehajtásáról: Lekérdezés végrehajtása.
Jegyzet
A Contains metódus az adatbázisban fut, nem a C# kódban. A lekérdezés kis- és nagybetűk érzékenysége az adatbázistól és a kollációtól függ. Az SQL Serveren a Contains a SQL LIKEértékre képezhető le, ami nem érzékeny a kis- és nagybetűkre. Az alapértelmezett rendezéssel rendelkező SQLite esetében a kis- és nagybetű érzékenység keveredik, az éppen használt lekérdezéstől függően. IN Az esetérzékeny SQLite-lekérdezések készítésével kapcsolatos információkért tekintse meg a következőket:
Irányítson a /Movies/Index-ra. Adjon hozzá egy lekérdezési sztringet, például ?searchString=Ghost az URL-címhez. A szűrt filmek megjelennek.
Ha úgy módosítja a Index metódus aláírását, hogy egy idnevű paraméterrel rendelkezzen, a id paraméter megfelel az {id}alapértelmezett útvonalainak választható Program.cs helyőrzőjének.
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
Módosítsa a paraméter értékét id-ra, és módosítsa a searchString összes előfordulását id-re.
Az előző Index metódus:
public async Task<IActionResult> Index(string searchString)
{
if (_context.Movie == null)
{
return Problem("Entity set 'MvcMovieContext.Movie' is null.");
}
var movies = from m in _context.Movie
select m;
if (!String.IsNullOrEmpty(searchString))
{
movies = movies.Where(s => s.Title!.ToUpper().Contains(searchString.ToUpper()));
}
return View(await movies.ToListAsync());
}
A frissített Index metódus id paraméterrel:
public async Task<IActionResult> Index(string id)
{
if (_context.Movie == null)
{
return Problem("Entity set 'MvcMovieContext.Movie' is null.");
}
var movies = from m in _context.Movie
select m;
if (!String.IsNullOrEmpty(id))
{
movies = movies.Where(s => s.Title!.ToUpper().Contains(id.ToUpper()));
}
return View(await movies.ToListAsync());
}
A keresési címet mostantól útvonaladatként (URL-szegmensként) is átadhatja lekérdezési sztringérték helyett.
Azonban nem számíthat arra, hogy a felhasználók minden alkalommal módosítják az URL-címet, amikor filmet szeretnének keresni. Így most felhasználói felületi elemeket fog hozzáadni, hogy segítsen nekik a filmek szűrésében. Ha módosította a Index metódus aláírását az útvonalhoz kötött ID paraméter átadásának teszteléséhez, módosítsa vissza, hogy egy searchStringnevű paramétert használjon:
public async Task<IActionResult> Index(string searchString)
{
if (_context.Movie == null)
{
return Problem("Entity set 'MvcMovieContext.Movie' is null.");
}
var movies = from m in _context.Movie
select m;
if (!String.IsNullOrEmpty(searchString))
{
movies = movies.Where(s => s.Title!.ToUpper().Contains(searchString.ToUpper()));
}
return View(await movies.ToListAsync());
}
Nyissa meg a Views/Movies/Index.cshtml fájlt, és adja hozzá az alább kiemelt <form> jelölést:
@model IEnumerable<MvcMovie.Models.Movie>
@{
ViewData["Title"] = "Index";
}
<h1>Index</h1>
<p>
<a asp-action="Create">Create New</a>
</p>
<form asp-controller="Movies" asp-action="Index">
<p>
<label>Title: <input type="text" name="SearchString" /></label>
<input type="submit" value="Filter" />
</p>
</form>
<table class="table">
A HTML-<form> címke az űrlapcímke-segéd-t használja, így az űrlap feladásakor a szűrő karakterlánc a filmvezérlő Index művelethez kerül továbbításra. Mentse a módosításokat, majd tesztelje a szűrőt.
A [HttpPost] metódusnak nincs Index túlterhelése, ahogy várható. Nincs rá szükség, mert a metódus nem módosítja az alkalmazás állapotát, csak szűri az adatokat.
A következő [HttpPost] Index metódust adhatja hozzá.
[HttpPost]
public string Index(string searchString, bool notUsed)
{
return "From [HttpPost]Index: filter on " + searchString;
}
A notUsed paraméter a Index metódus túlterhelésének létrehozására szolgál. Erről az oktatóanyag későbbi részében lesz szó.
Ha hozzáadja ezt a metódust, a műveletindító megfelel a [HttpPost] Index metódusnak, és a [HttpPost] Index metódus az alábbi képen látható módon fut.
Azonban még akkor is, ha hozzáadja a [HttpPost] metódus ezen Index verzióját, van egy korlátozás abban, ahogyan mindez megvalósításra került. Tegyük fel, hogy egy adott keresést szeretne könyvjelzővel megjelölni, vagy egy olyan hivatkozást szeretne küldeni barátainak, amelyekre kattintva megtekintheti a filmek szűrt listáját. Figyelje meg, hogy a HTTP POST-kérelem URL-címe megegyezik a GET-kérés URL-címével (localhost:{PORT}/Movies/Index) – az URL-címben nincs keresési információ. A keresési sztring adatait a rendszer űrlapmező-értékként küldi el a kiszolgálónak. Ellenőrizheti a böngésző fejlesztői eszközeinek vagy a kiváló Fiddler eszköznek a segítségével. Az alábbi képen a Chrome böngésző fejlesztői eszközei láthatók:
A keresési paraméter és a XSRF token a kérelem törzsében látható. Vegye figyelembe, hogy az előző oktatóanyagban említett módon az űrlappéldány-segítő létrehoz egy XSRF hamisítás elleni tokent. Nem módosítjuk az adatokat, ezért nem kell érvényesítenünk a jogkivonatot a vezérlőmetódusban.
Mivel a keresési paraméter nem az URL-cím, hanem a kérelem törzsében található, ezeket a keresési adatokat nem rögzítheti könyvjelzőként vagy másokkal való megosztáshoz. Ezt úgy oldhatja meg, hogy megadja, hogy a kérés a HTTP GET fájlban található Views/Movies/Index.cshtml legyen.
@model IEnumerable<MvcMovie.Models.Movie>
@{
ViewData["Title"] = "Index";
}
<h1>Index</h1>
<p>
<a asp-action="Create">Create New</a>
</p>
<form asp-controller="Movies" asp-action="Index" method="get">
<p>
<label>Title: <input type="text" name="SearchString" /></label>
<input type="submit" value="Filter" />
</p>
</form>
<table class="table">
Most, amikor elküld egy keresést, az URL-cím tartalmazza a keresési lekérdezési sztringet. A keresés a HttpGet Index műveletmetódusra is vonatkozik, még akkor is, ha rendelkezik HttpPost Index metódussal.
Az alábbi korrektúra a form címkére való váltást mutatja be:
<form asp-controller="Movies" asp-action="Index" method="get">
Keresés hozzáadása műfaj szerint
Adja hozzá a következő MovieGenreViewModel osztályt a Modellek mappához:
using Microsoft.AspNetCore.Mvc.Rendering;
using System.Collections.Generic;
namespace MvcMovie.Models;
public class MovieGenreViewModel
{
public List<Movie>? Movies { get; set; }
public SelectList? Genres { get; set; }
public string? MovieGenre { get; set; }
public string? SearchString { get; set; }
}
A film-műfaj nézetmodell a következőket tartalmazza:
- A filmek listája.
- A műfajok listáját tartalmazó
SelectList. Így a felhasználó kiválaszthat egy műfajt a listából. -
MovieGenre, amely a kiválasztott műfajt tartalmazza. -
SearchString, amely a keresőmezőbe beírt szöveget tartalmazza.
Cserélje le a Index metódust a MoviesController.cs-ban/-ben a következő kódra:
// GET: Movies
public async Task<IActionResult> Index(string movieGenre, string searchString)
{
if (_context.Movie == null)
{
return Problem("Entity set 'MvcMovieContext.Movie' is null.");
}
// 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!.ToUpper().Contains(searchString.ToUpper()));
}
if (!string.IsNullOrEmpty(movieGenre))
{
movies = movies.Where(x => x.Genre == movieGenre);
}
var movieGenreVM = new MovieGenreViewModel
{
Genres = new SelectList(await genreQuery.Distinct().ToListAsync()),
Movies = await movies.ToListAsync()
};
return View(movieGenreVM);
}
Az alábbi kód egy LINQ lekérdezés, amely lekéri az összes műfajt az adatbázisból.
// Use LINQ to get list of genres.
IQueryable<string> genreQuery = from m in _context.Movie
orderby m.Genre
select m.Genre;
A műfajok SelectList a különböző műfajok kivetítésével jön létre (nem szeretnénk, hogy a kiválasztási lista duplikált műfajokkal rendelkezzen).
Amikor a felhasználó megkeresi az elemet, a keresési érték megmarad a keresőmezőben.
Keresés hozzáadása műfaj szerint az Index nézethez
A Index.cshtml frissítése megtalálható a Nézetek/Filmek/ alatt az alábbiak szerint:
@model MvcMovie.Models.MovieGenreViewModel
@{
ViewData["Title"] = "Index";
}
<h1>Index</h1>
<p>
<a asp-action="Create">Create New</a>
</p>
<form asp-controller="Movies" asp-action="Index" method="get">
<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">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Movies![0].Title)
</th>
<th>
@Html.DisplayNameFor(model => model.Movies![0].ReleaseDate)
</th>
<th>
@Html.DisplayNameFor(model => model.Movies![0].Genre)
</th>
<th>
@Html.DisplayNameFor(model => model.Movies![0].Price)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.Movies!)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.ReleaseDate)
</td>
<td>
@Html.DisplayFor(modelItem => item.Genre)
</td>
<td>
@Html.DisplayFor(modelItem => item.Price)
</td>
<td>
<a asp-action="Edit" asp-route-id="@item.Id">Edit</a> |
<a asp-action="Details" asp-route-id="@item.Id">Details</a> |
<a asp-action="Delete" asp-route-id="@item.Id">Delete</a>
</td>
</tr>
}
</tbody>
</table>
Vizsgálja meg a következő HTML-segédben használt lambda kifejezést:
@Html.DisplayNameFor(model => model.Movies![0].Title)
Az előző kódban a DisplayNameFor HTML-segéd a lambda kifejezésben hivatkozott Title tulajdonságot vizsgálja a megjelenítendő név meghatározásához. Mivel a lambda kifejezést nem kiértékelik, nem kap hozzáférési szabálysértést, ha model, model.Moviesvagy model.Movies[0]null vagy üres. A lambda kifejezés kiértékelésekor (például @Html.DisplayFor(modelItem => item.Title)) a modell tulajdonságértékei lesznek kiértékelve. A ! utáni model.Movies a null-megbocsátó operátor, amelyet annak deklarálására használnak, hogy a Movies nem nulla.
Tesztelje az alkalmazást műfaj, filmcím és mindkettő alapján:
Ebben a szakaszban keresési funkciót ad hozzá a Index műveletmetódushoz, amely lehetővé teszi a filmek keresését műfaji vagy névalapján.
Frissítse a Index metódust, amely a Controllers/MoviesController.cs-ben található, a következő kóddal:
public async Task<IActionResult> Index(string searchString)
{
if (_context.Movie == null)
{
return Problem("Entity set 'MvcMovieContext.Movie' is null.");
}
var movies = from m in _context.Movie
select m;
if (!String.IsNullOrEmpty(searchString))
{
movies = movies.Where(s => s.Title!.ToUpper().Contains(searchString.ToUpper()));
}
return View(await movies.ToListAsync());
}
A Index műveletmetódus következő sora létrehoz egy LINQ lekérdezést a filmek kiválasztásához:
var movies = from m in _context.Movie
select m;
A lekérdezés jelenleg csak van definiálva; még nem lett futtatva az adatbázison.
Ha a searchString paraméter tartalmaz egy sztringet, a rendszer úgy módosítja a mozgókép-lekérdezést, hogy a keresési sztring értékére szűrjön:
if (!String.IsNullOrEmpty(searchString))
{
movies = movies.Where(s => s.Title!.ToUpper().Contains(searchString.ToUpper()));
}
A fenti s => s.Title!.ToUpper().Contains(searchString.ToUpper()) kód egy Lambda Expression. A lambdákat a metódusalapú LINQ lekérdezésekben használják a standard lekérdezési operátor metódusok, mint például a Where metódus vagy a Contains (használva a fenti kódban), argumentumaként. A LINQ-lekérdezések nem lesznek végrehajtva, amikor definiálják őket, vagy ha módosítják őket egy olyan metódus meghívásával, mint például Where, Containsvagy OrderBy. Ehelyett a lekérdezések végrehajtása halasztva van. Ez azt jelenti, hogy egy kifejezés kiértékelése késleltetve van, amíg a realizált értéket ténylegesen végig nem iterálják, vagy amíg a ToListAsync metódust meg nem hívják. További információ a halasztott lekérdezések végrehajtásáról: Lekérdezés végrehajtása.
Jegyzet
A Contains metódus az adatbázisban fut, nem a C# kódban. A lekérdezés kis- és nagybetűk érzékenysége az adatbázistól és a kollációtól függ. Az SQL Serveren a Contains a SQL LIKEértékre képezhető le, ami nem érzékeny a kis- és nagybetűkre. Az alapértelmezett rendezéssel rendelkező SQLite esetében a kis- és nagybetű érzékenység keveredik, az éppen használt lekérdezéstől függően. IN Az esetérzékeny SQLite-lekérdezések készítésével kapcsolatos információkért tekintse meg a következőket:
Irányítson a /Movies/Index-ra. Adjon hozzá egy lekérdezési sztringet, például ?searchString=Ghost az URL-címhez. A szűrt filmek megjelennek.
Ha úgy módosítja a Index metódus aláírását, hogy egy idnevű paraméterrel rendelkezzen, a id paraméter megfelel az {id}alapértelmezett útvonalainak választható Program.cs helyőrzőjének.
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
Módosítsa a paraméter értékét id-ra, és módosítsa a searchString összes előfordulását id-re.
Az előző Index metódus:
public async Task<IActionResult> Index(string searchString)
{
if (_context.Movie == null)
{
return Problem("Entity set 'MvcMovieContext.Movie' is null.");
}
var movies = from m in _context.Movie
select m;
if (!String.IsNullOrEmpty(searchString))
{
movies = movies.Where(s => s.Title!.ToUpper().Contains(searchString.ToUpper()));
}
return View(await movies.ToListAsync());
}
A frissített Index metódus id paraméterrel:
public async Task<IActionResult> Index(string id)
{
if (_context.Movie == null)
{
return Problem("Entity set 'MvcMovieContext.Movie' is null.");
}
var movies = from m in _context.Movie
select m;
if (!String.IsNullOrEmpty(id))
{
movies = movies.Where(s => s.Title!.ToUpper().Contains(id.ToUpper()));
}
return View(await movies.ToListAsync());
}
A keresési címet mostantól útvonaladatként (URL-szegmensként) is átadhatja lekérdezési sztringérték helyett.
Azonban nem számíthat arra, hogy a felhasználók minden alkalommal módosítják az URL-címet, amikor filmet szeretnének keresni. Így most felhasználói felületi elemeket fog hozzáadni, hogy segítsen nekik a filmek szűrésében. Ha módosította a Index metódus aláírását az útvonalhoz kötött ID paraméter átadásának teszteléséhez, módosítsa vissza, hogy egy searchStringnevű paramétert használjon:
public async Task<IActionResult> Index(string searchString)
{
if (_context.Movie == null)
{
return Problem("Entity set 'MvcMovieContext.Movie' is null.");
}
var movies = from m in _context.Movie
select m;
if (!String.IsNullOrEmpty(searchString))
{
movies = movies.Where(s => s.Title!.ToUpper().Contains(searchString.ToUpper()));
}
return View(await movies.ToListAsync());
}
Nyissa meg a Views/Movies/Index.cshtml fájlt, és adja hozzá az alább kiemelt <form> jelölést:
@model IEnumerable<MvcMovie.Models.Movie>
@{
ViewData["Title"] = "Index";
}
<h1>Index</h1>
<p>
<a asp-action="Create">Create New</a>
</p>
<form asp-controller="Movies" asp-action="Index">
<p>
<label>Title: <input type="text" name="SearchString" /></label>
<input type="submit" value="Filter" />
</p>
</form>
<table class="table">
A HTML-<form> címke az űrlapcímke-segéd-t használja, így az űrlap feladásakor a szűrő karakterlánc a filmvezérlő Index művelethez kerül továbbításra. Mentse a módosításokat, majd tesztelje a szűrőt.
A [HttpPost] metódusnak nincs Index túlterhelése, ahogy várható. Nincs rá szükség, mert a metódus nem módosítja az alkalmazás állapotát, csak szűri az adatokat.
A következő [HttpPost] Index metódust adhatja hozzá.
[HttpPost]
public string Index(string searchString, bool notUsed)
{
return "From [HttpPost]Index: filter on " + searchString;
}
A notUsed paraméter a Index metódus túlterhelésének létrehozására szolgál. Erről az oktatóanyag későbbi részében lesz szó.
Ha hozzáadja ezt a metódust, a műveletindító megfelel a [HttpPost] Index metódusnak, és a [HttpPost] Index metódus az alábbi képen látható módon fut.
Azonban még akkor is, ha hozzáadja a [HttpPost] metódus ezen Index verzióját, van egy korlátozás abban, ahogyan mindez megvalósításra került. Tegyük fel, hogy egy adott keresést szeretne könyvjelzővel megjelölni, vagy egy olyan hivatkozást szeretne küldeni barátainak, amelyekre kattintva megtekintheti a filmek szűrt listáját. Figyelje meg, hogy a HTTP POST-kérelem URL-címe megegyezik a GET-kérés URL-címével (localhost:{PORT}/Movies/Index) – az URL-címben nincs keresési információ. A keresési sztring adatait a rendszer űrlapmező-értékként küldi el a kiszolgálónak. Ellenőrizheti a böngésző fejlesztői eszközeinek vagy a kiváló Fiddler eszköznek a segítségével. Az alábbi képen a Chrome böngésző fejlesztői eszközei láthatók:
A keresési paraméter és a XSRF token a kérelem törzsében látható. Vegye figyelembe, hogy az előző oktatóanyagban említett módon az űrlappéldány-segítő létrehoz egy XSRF hamisítás elleni tokent. Nem módosítjuk az adatokat, ezért nem kell érvényesítenünk a jogkivonatot a vezérlőmetódusban.
Mivel a keresési paraméter nem az URL-cím, hanem a kérelem törzsében található, ezeket a keresési adatokat nem rögzítheti könyvjelzőként vagy másokkal való megosztáshoz. Ezt úgy oldhatja meg, hogy megadja, hogy a kérés a HTTP GET fájlban található Views/Movies/Index.cshtml legyen.
@model IEnumerable<MvcMovie.Models.Movie>
@{
ViewData["Title"] = "Index";
}
<h1>Index</h1>
<p>
<a asp-action="Create">Create New</a>
</p>
<form asp-controller="Movies" asp-action="Index" method="get">
<p>
<label>Title: <input type="text" name="SearchString" /></label>
<input type="submit" value="Filter" />
</p>
</form>
<table class="table">
Most, amikor elküld egy keresést, az URL-cím tartalmazza a keresési lekérdezési sztringet. A keresés a HttpGet Index műveletmetódusra is vonatkozik, még akkor is, ha rendelkezik HttpPost Index metódussal.
Az alábbi korrektúra a form címkére való váltást mutatja be:
<form asp-controller="Movies" asp-action="Index" method="get">
Keresés hozzáadása műfaj szerint
Adja hozzá a következő MovieGenreViewModel osztályt a Modellek mappához:
using Microsoft.AspNetCore.Mvc.Rendering;
using System.Collections.Generic;
namespace MvcMovie.Models;
public class MovieGenreViewModel
{
public List<Movie>? Movies { get; set; }
public SelectList? Genres { get; set; }
public string? MovieGenre { get; set; }
public string? SearchString { get; set; }
}
A film-műfaj nézetmodell a következőket tartalmazza:
- A filmek listája.
- A műfajok listáját tartalmazó
SelectList. Így a felhasználó kiválaszthat egy műfajt a listából. -
MovieGenre, amely a kiválasztott műfajt tartalmazza. -
SearchString, amely a keresőmezőbe beírt szöveget tartalmazza.
Cserélje le a Index metódust a MoviesController.cs-ban/-ben a következő kódra:
// GET: Movies
public async Task<IActionResult> Index(string movieGenre, string searchString)
{
if (_context.Movie == null)
{
return Problem("Entity set 'MvcMovieContext.Movie' is null.");
}
// 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!.ToUpper().Contains(searchString.ToUpper()));
}
if (!string.IsNullOrEmpty(movieGenre))
{
movies = movies.Where(x => x.Genre == movieGenre);
}
var movieGenreVM = new MovieGenreViewModel
{
Genres = new SelectList(await genreQuery.Distinct().ToListAsync()),
Movies = await movies.ToListAsync()
};
return View(movieGenreVM);
}
Az alábbi kód egy LINQ lekérdezés, amely lekéri az összes műfajt az adatbázisból.
// Use LINQ to get list of genres.
IQueryable<string> genreQuery = from m in _context.Movie
orderby m.Genre
select m.Genre;
A műfajok SelectList a különböző műfajok kivetítésével jön létre (nem szeretnénk, hogy a kiválasztási lista duplikált műfajokkal rendelkezzen).
Amikor a felhasználó megkeresi az elemet, a keresési érték megmarad a keresőmezőben.
Keresés hozzáadása műfaj szerint az Index nézethez
A Index.cshtml frissítése megtalálható a Nézetek/Filmek/ alatt az alábbiak szerint:
@model MvcMovie.Models.MovieGenreViewModel
@{
ViewData["Title"] = "Index";
}
<h1>Index</h1>
<p>
<a asp-action="Create">Create New</a>
</p>
<form asp-controller="Movies" asp-action="Index" method="get">
<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">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Movies![0].Title)
</th>
<th>
@Html.DisplayNameFor(model => model.Movies![0].ReleaseDate)
</th>
<th>
@Html.DisplayNameFor(model => model.Movies![0].Genre)
</th>
<th>
@Html.DisplayNameFor(model => model.Movies![0].Price)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.Movies!)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.ReleaseDate)
</td>
<td>
@Html.DisplayFor(modelItem => item.Genre)
</td>
<td>
@Html.DisplayFor(modelItem => item.Price)
</td>
<td>
<a asp-action="Edit" asp-route-id="@item.Id">Edit</a> |
<a asp-action="Details" asp-route-id="@item.Id">Details</a> |
<a asp-action="Delete" asp-route-id="@item.Id">Delete</a>
</td>
</tr>
}
</tbody>
</table>
Vizsgálja meg a következő HTML-segédben használt lambda kifejezést:
@Html.DisplayNameFor(model => model.Movies![0].Title)
Az előző kódban a DisplayNameFor HTML-segéd a lambda kifejezésben hivatkozott Title tulajdonságot vizsgálja a megjelenítendő név meghatározásához. Mivel a lambda kifejezést nem kiértékelik, nem kap hozzáférési szabálysértést, ha model, model.Moviesvagy model.Movies[0]null vagy üres. A lambda kifejezés kiértékelésekor (például @Html.DisplayFor(modelItem => item.Title)) a modell tulajdonságértékei lesznek kiértékelve. A ! utáni model.Movies a null-megbocsátó operátor, amelyet annak deklarálására használnak, hogy a Movies nem nulla.
Tesztelje az alkalmazást műfaj, filmcím és mindkettő alapján:
Ebben a szakaszban keresési funkciót ad hozzá a Index műveletmetódushoz, amely lehetővé teszi a filmek keresését műfaji vagy névalapján.
Frissítse a Index metódust, amely a Controllers/MoviesController.cs-ben található, a következő kóddal:
public async Task<IActionResult> Index(string searchString)
{
var movies = from m in _context.Movie
select m;
if (!String.IsNullOrEmpty(searchString))
{
movies = movies.Where(s => s.Title!.Contains(searchString));
}
return View(await movies.ToListAsync());
}
A Index műveletmetódus első sora létrehoz egy LINQ lekérdezést a filmek kiválasztásához:
var movies = from m in _context.Movie
select m;
A lekérdezés jelenleg csak van definiálva; még nem lett futtatva az adatbázison.
Ha a searchString paraméter tartalmaz egy sztringet, a rendszer úgy módosítja a mozgókép-lekérdezést, hogy a keresési sztring értékére szűrjön:
if (!String.IsNullOrEmpty(searchString))
{
movies = movies.Where(s => s.Title!.Contains(searchString));
}
A fenti s => s.Title!.Contains(searchString) kód egy Lambda Expression. A lambdákat a metódusalapú LINQ lekérdezésekben használják a standard lekérdezési operátor metódusok, mint például a Where metódus vagy a Contains (használva a fenti kódban), argumentumaként. A LINQ-lekérdezések nem lesznek végrehajtva, amikor definiálják őket, vagy ha módosítják őket egy olyan metódus meghívásával, mint például Where, Containsvagy OrderBy. Ehelyett a lekérdezések végrehajtása halasztva van. Ez azt jelenti, hogy egy kifejezés kiértékelése késleltetve van, amíg a realizált értéket ténylegesen végig nem iterálják, vagy amíg a ToListAsync metódust meg nem hívják. További információ a halasztott lekérdezések végrehajtásáról: Lekérdezés végrehajtása.
Megjegyzés: A Contains metódus az adatbázisban fut, nem a fent látható c# kódban. A lekérdezés kis- és nagybetűk érzékenysége az adatbázistól és a kollációtól függ. Az SQL Serveren a Contains a SQL LIKEértékre képezhető le, ami nem érzékeny a kis- és nagybetűkre. Az SQLite-ben az alapértelmezett rendezéssel a kis- és nagybetűk megkülönböztetése érvényesül.
Irányítson a /Movies/Index-ra. Adjon hozzá egy lekérdezési sztringet, például ?searchString=Ghost az URL-címhez. A szűrt filmek megjelennek.
Ha úgy módosítja a Index metódus aláírását, hogy egy idnevű paraméterrel rendelkezzen, a id paraméter megfelel az {id}alapértelmezett útvonalainak választható Program.cs helyőrzőjének.
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
Módosítsa a paraméter értékét id-ra, és módosítsa a searchString összes előfordulását id-re.
Az előző Index metódus:
public async Task<IActionResult> Index(string searchString)
{
var movies = from m in _context.Movie
select m;
if (!String.IsNullOrEmpty(searchString))
{
movies = movies.Where(s => s.Title!.Contains(searchString));
}
return View(await movies.ToListAsync());
}
A frissített Index metódus id paraméterrel:
public async Task<IActionResult> Index(string id)
{
var movies = from m in _context.Movie
select m;
if (!String.IsNullOrEmpty(id))
{
movies = movies.Where(s => s.Title!.Contains(id));
}
return View(await movies.ToListAsync());
}
A keresési címet mostantól útvonaladatként (URL-szegmensként) is átadhatja lekérdezési sztringérték helyett.
Azonban nem számíthat arra, hogy a felhasználók minden alkalommal módosítják az URL-címet, amikor filmet szeretnének keresni. Így most felhasználói felületi elemeket fog hozzáadni, hogy segítsen nekik a filmek szűrésében. Ha módosította a Index metódus aláírását az útvonalhoz kötött ID paraméter átadásának teszteléséhez, módosítsa vissza, hogy egy searchStringnevű paramétert használjon:
public async Task<IActionResult> Index(string searchString)
{
var movies = from m in _context.Movie
select m;
if (!String.IsNullOrEmpty(searchString))
{
movies = movies.Where(s => s.Title!.Contains(searchString));
}
return View(await movies.ToListAsync());
}
Nyissa meg a Views/Movies/Index.cshtml fájlt, és adja hozzá az alább kiemelt <form> jelölést:
@model IEnumerable<MvcMovie.Models.Movie>
@{
ViewData["Title"] = "Index";
}
<h2>Index</h2>
<p>
<a asp-action="Create">Create New</a>
</p>
<form asp-controller="Movies" asp-action="Index">
<p>
<label>Title: <input type="text" name="SearchString" /></label>
<input type="submit" value="Filter" />
</p>
</form>
A HTML-<form> címke az űrlapcímke-segéd-t használja, így az űrlap feladásakor a szűrő karakterlánc a filmvezérlő Index művelethez kerül továbbításra. Mentse a módosításokat, majd tesztelje a szűrőt.
A [HttpPost] metódusnak nincs Index túlterhelése, ahogy várható. Nincs rá szükség, mert a metódus nem módosítja az alkalmazás állapotát, csak szűri az adatokat.
A következő [HttpPost] Index metódust adhatja hozzá.
[HttpPost]
public string Index(string searchString, bool notUsed)
{
return "From [HttpPost]Index: filter on " + searchString;
}
A notUsed paraméter a Index metódus túlterhelésének létrehozására szolgál. Erről az oktatóanyag későbbi részében lesz szó.
Ha hozzáadja ezt a metódust, a műveletindító megfelel a [HttpPost] Index metódusnak, és a [HttpPost] Index metódus az alábbi képen látható módon fut.
Azonban még akkor is, ha hozzáadja a [HttpPost] metódus ezen Index verzióját, van egy korlátozás abban, ahogyan mindez megvalósításra került. Tegyük fel, hogy egy adott keresést szeretne könyvjelzővel megjelölni, vagy egy olyan hivatkozást szeretne küldeni barátainak, amelyekre kattintva megtekintheti a filmek szűrt listáját. Figyelje meg, hogy a HTTP POST-kérelem URL-címe megegyezik a GET-kérés URL-címével (localhost:{PORT}/Movies/Index) – az URL-címben nincs keresési információ. A keresési sztring adatait a rendszer űrlapmező-értékként küldi el a kiszolgálónak. Ellenőrizheti a böngésző fejlesztői eszközeinek vagy a kiváló Fiddler eszköznek a segítségével. Az alábbi képen a Chrome böngésző fejlesztői eszközei láthatók:
A keresési paraméter és a XSRF token a kérelem törzsében látható. Vegye figyelembe, hogy az előző oktatóanyagban említett módon az űrlappéldány-segítő létrehoz egy XSRF hamisítás elleni tokent. Nem módosítjuk az adatokat, ezért nem kell érvényesítenünk a jogkivonatot a vezérlőmetódusban.
Mivel a keresési paraméter nem az URL-cím, hanem a kérelem törzsében található, ezeket a keresési adatokat nem rögzítheti könyvjelzőként vagy másokkal való megosztáshoz. Ezt úgy oldhatja meg, hogy megadja, hogy a kérés a HTTP GET fájlban található Views/Movies/Index.cshtml legyen.
@model IEnumerable<MvcMovie.Models.Movie>
@{
ViewData["Title"] = "Index";
}
<h1>Index</h1>
<p>
<a asp-action="Create">Create New</a>
</p>
<form asp-controller="Movies" asp-action="Index" method="get">
<p>
<label>Title: <input type="text" name="SearchString" /></label>
<input type="submit" value="Filter" />
</p>
</form>
<table class="table">
Most, amikor elküld egy keresést, az URL-cím tartalmazza a keresési lekérdezési sztringet. A keresés a HttpGet Index műveletmetódusra is vonatkozik, még akkor is, ha rendelkezik HttpPost Index metódussal.
Az alábbi korrektúra a form címkére való váltást mutatja be:
<form asp-controller="Movies" asp-action="Index" method="get">
Keresés hozzáadása műfaj szerint
Adja hozzá a következő MovieGenreViewModel osztályt a Modellek mappához:
using Microsoft.AspNetCore.Mvc.Rendering;
using System.Collections.Generic;
namespace MvcMovie.Models
{
public class MovieGenreViewModel
{
public List<Movie>? Movies { get; set; }
public SelectList? Genres { get; set; }
public string? MovieGenre { get; set; }
public string? SearchString { get; set; }
}
}
A film-műfaj nézetmodell a következőket tartalmazza:
- A filmek listája.
- A műfajok listáját tartalmazó
SelectList. Így a felhasználó kiválaszthat egy műfajt a listából. -
MovieGenre, amely a kiválasztott műfajt tartalmazza. -
SearchString, amely a keresőmezőbe beírt szöveget tartalmazza.
Cserélje le a Index metódust a MoviesController.cs-ban/-ben a következő kódra:
// GET: Movies
public async Task<IActionResult> Index(string movieGenre, string searchString)
{
// 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);
}
var movieGenreVM = new MovieGenreViewModel
{
Genres = new SelectList(await genreQuery.Distinct().ToListAsync()),
Movies = await movies.ToListAsync()
};
return View(movieGenreVM);
}
Az alábbi kód egy LINQ lekérdezés, amely lekéri az összes műfajt az adatbázisból.
// Use LINQ to get list of genres.
IQueryable<string> genreQuery = from m in _context.Movie
orderby m.Genre
select m.Genre;
A műfajok SelectList a különböző műfajok kivetítésével jön létre (nem szeretnénk, hogy a kiválasztási lista duplikált műfajokkal rendelkezzen).
Amikor a felhasználó megkeresi az elemet, a keresési érték megmarad a keresőmezőben.
Keresés hozzáadása műfaj szerint az Index nézethez
A Index.cshtml frissítése megtalálható a Nézetek/Filmek/ alatt az alábbiak szerint:
@model MvcMovie.Models.MovieGenreViewModel
@{
ViewData["Title"] = "Index";
}
<h1>Index</h1>
<p>
<a asp-action="Create">Create New</a>
</p>
<form asp-controller="Movies" asp-action="Index" method="get">
<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">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Movies[0].Title)
</th>
<th>
@Html.DisplayNameFor(model => model.Movies[0].ReleaseDate)
</th>
<th>
@Html.DisplayNameFor(model => model.Movies[0].Genre)
</th>
<th>
@Html.DisplayNameFor(model => model.Movies[0].Price)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.Movies)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.ReleaseDate)
</td>
<td>
@Html.DisplayFor(modelItem => item.Genre)
</td>
<td>
@Html.DisplayFor(modelItem => item.Price)
</td>
<td>
<a asp-action="Edit" asp-route-id="@item.Id">Edit</a> |
<a asp-action="Details" asp-route-id="@item.Id">Details</a> |
<a asp-action="Delete" asp-route-id="@item.Id">Delete</a>
</td>
</tr>
}
</tbody>
</table>
Vizsgálja meg a következő HTML-segédben használt lambda kifejezést:
@Html.DisplayNameFor(model => model.Movies[0].Title)
Az előző kódban a DisplayNameFor HTML-segéd a lambda kifejezésben hivatkozott Title tulajdonságot vizsgálja a megjelenítendő név meghatározásához. Mivel a lambda kifejezést nem kiértékelik, nem kap hozzáférési szabálysértést, ha model, model.Moviesvagy model.Movies[0]null vagy üres. A lambda kifejezés kiértékelésekor (például @Html.DisplayFor(modelItem => item.Title)) a modell tulajdonságértékei lesznek kiértékelve.
Tesztelje az alkalmazást műfaj, filmcím és mindkettő alapján:
Ebben a szakaszban keresési funkciót ad hozzá a Index műveletmetódushoz, amely lehetővé teszi a filmek keresését műfaji vagy névalapján.
Frissítse a Index metódust, amely a Controllers/MoviesController.cs-ben található, a következő kóddal:
public async Task<IActionResult> Index(string searchString)
{
var movies = from m in _context.Movie
select m;
if (!String.IsNullOrEmpty(searchString))
{
movies = movies.Where(s => s.Title.Contains(searchString));
}
return View(await movies.ToListAsync());
}
A Index műveletmetódus első sora létrehoz egy LINQ lekérdezést a filmek kiválasztásához:
var movies = from m in _context.Movie
select m;
A lekérdezés jelenleg csak van definiálva, nem futtatva az adatbázison.
Ha a searchString paraméter tartalmaz egy sztringet, a rendszer úgy módosítja a mozgókép-lekérdezést, hogy a keresési sztring értékére szűrjön:
if (!String.IsNullOrEmpty(searchString))
{
movies = movies.Where(s => s.Title.Contains(searchString));
}
A fenti s => s.Title.Contains() kód egy Lambda Expression. A lambdákat a metódusalapú LINQ lekérdezésekben használják a standard lekérdezési operátor metódusok, mint például a Where metódus vagy a Contains (használva a fenti kódban), argumentumaként. A LINQ-lekérdezések nem lesznek végrehajtva, amikor definiálják őket, vagy ha módosítják őket egy olyan metódus meghívásával, mint például Where, Containsvagy OrderBy. Ehelyett a lekérdezések végrehajtása halasztva van. Ez azt jelenti, hogy egy kifejezés kiértékelése késleltetve van, amíg a realizált értéket ténylegesen végig nem iterálják, vagy amíg a ToListAsync metódust meg nem hívják. További információ a halasztott lekérdezések végrehajtásáról: Lekérdezés végrehajtása.
Megjegyzés: A Contains metódus az adatbázisban fut, nem a fent látható c# kódban. A lekérdezés kis- és nagybetűk érzékenysége az adatbázistól és a kollációtól függ. Az SQL Serveren a Contains a SQL LIKEértékre képezhető le, ami nem érzékeny a kis- és nagybetűkre. Az SQLite-ben az alapértelmezett rendezéssel a kis- és nagybetűk megkülönböztetése érvényesül.
Irányítson a /Movies/Index-ra. Adjon hozzá egy lekérdezési sztringet, például ?searchString=Ghost az URL-címhez. A szűrt filmek megjelennek.
Ha úgy módosítja a Index metódus aláírását, hogy egy idnevű paraméterrel rendelkezzen, a id paraméter megfelel az {id}alapértelmezett útvonalainak választható Startup.cs helyőrzőjének.
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
Módosítsa a paramétert id-ra, majd searchString összes előfordulását id-re.
Az előző Index metódus:
public async Task<IActionResult> Index(string searchString)
{
var movies = from m in _context.Movie
select m;
if (!String.IsNullOrEmpty(searchString))
{
movies = movies.Where(s => s.Title.Contains(searchString));
}
return View(await movies.ToListAsync());
}
A frissített Index metódus id paraméterrel:
public async Task<IActionResult> Index(string id)
{
var movies = from m in _context.Movie
select m;
if (!String.IsNullOrEmpty(id))
{
movies = movies.Where(s => s.Title.Contains(id));
}
return View(await movies.ToListAsync());
}
A keresési címet mostantól útvonaladatként (URL-szegmensként) is átadhatja lekérdezési sztringérték helyett.
Azonban nem számíthat arra, hogy a felhasználók minden alkalommal módosítják az URL-címet, amikor filmet szeretnének keresni. Így most felhasználói felületi elemeket fog hozzáadni, hogy segítsen nekik a filmek szűrésében. Ha módosította a Index metódus aláírását az útvonalhoz kötött ID paraméter átadásának teszteléséhez, módosítsa vissza, hogy egy searchStringnevű paramétert használjon:
public async Task<IActionResult> Index(string searchString)
{
var movies = from m in _context.Movie
select m;
if (!String.IsNullOrEmpty(searchString))
{
movies = movies.Where(s => s.Title.Contains(searchString));
}
return View(await movies.ToListAsync());
}
Nyissa meg a Views/Movies/Index.cshtml fájlt, és adja hozzá az alább kiemelt <form> jelölést:
ViewData["Title"] = "Index";
}
<h2>Index</h2>
<p>
<a asp-action="Create">Create New</a>
</p>
<form asp-controller="Movies" asp-action="Index">
<p>
<label>Title: <input type="text" name="SearchString" /></label>
<input type="submit" value="Filter" />
</p>
</form>
<table class="table">
<thead>
A HTML-<form> címke az űrlapcímke-segéd-t használja, így az űrlap feladásakor a szűrő karakterlánc a filmvezérlő Index művelethez kerül továbbításra. Mentse a módosításokat, majd tesztelje a szűrőt.
A [HttpPost] metódusnak nincs Index túlterhelése, ahogy várható. Nincs rá szükség, mert a metódus nem módosítja az alkalmazás állapotát, csak szűri az adatokat.
A következő [HttpPost] Index metódust adhatja hozzá.
[HttpPost]
public string Index(string searchString, bool notUsed)
{
return "From [HttpPost]Index: filter on " + searchString;
}
A notUsed paraméter a Index metódus túlterhelésének létrehozására szolgál. Erről az oktatóanyag későbbi részében lesz szó.
Ha hozzáadja ezt a metódust, a műveletindító megfelel a [HttpPost] Index metódusnak, és a [HttpPost] Index metódus az alábbi képen látható módon fut.
Azonban még akkor is, ha hozzáadja a [HttpPost] metódus ezen Index verzióját, van egy korlátozás abban, ahogyan mindez megvalósításra került. Tegyük fel, hogy egy adott keresést szeretne könyvjelzővel megjelölni, vagy egy olyan hivatkozást szeretne küldeni barátainak, amelyekre kattintva megtekintheti a filmek szűrt listáját. Figyelje meg, hogy a HTTP POST-kérelem URL-címe megegyezik a GET-kérés URL-címével (localhost:{PORT}/Movies/Index) – az URL-címben nincs keresési információ. A keresési sztring adatait a rendszer űrlapmező-értékként küldi el a kiszolgálónak. Ellenőrizheti a böngésző fejlesztői eszközeinek vagy a kiváló Fiddler eszköznek a segítségével. Az alábbi képen a Chrome böngésző fejlesztői eszközei láthatók:
A keresési paraméter és a XSRF token a kérelem törzsében látható. Vegye figyelembe, hogy az előző oktatóanyagban említett módon az űrlappéldány-segítő létrehoz egy XSRF hamisítás elleni tokent. Nem módosítjuk az adatokat, ezért nem kell érvényesítenünk a jogkivonatot a vezérlőmetódusban.
Mivel a keresési paraméter nem az URL-cím, hanem a kérelem törzsében található, ezeket a keresési adatokat nem rögzítheti könyvjelzőként vagy másokkal való megosztáshoz. Ezt úgy oldhatja meg, hogy megadja, hogy a kérés a HTTP GET fájlban található Views/Movies/Index.cshtml legyen.
@model IEnumerable<MvcMovie.Models.Movie>
@{
ViewData["Title"] = "Index";
}
<h1>Index</h1>
<p>
<a asp-action="Create">Create New</a>
</p>
<form asp-controller="Movies" asp-action="Index" method="get">
<p>
<label>Title: <input type="text" name="SearchString" /></label>
<input type="submit" value="Filter" />
</p>
</form>
<table class="table">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Title)
Most, amikor elküld egy keresést, az URL-cím tartalmazza a keresési lekérdezési sztringet. A keresés a HttpGet Index műveletmetódusra is vonatkozik, még akkor is, ha rendelkezik HttpPost Index metódussal.
Az alábbi korrektúra a form címkére való váltást mutatja be:
<form asp-controller="Movies" asp-action="Index" method="get">
Keresés hozzáadása műfaj szerint
Adja hozzá a következő MovieGenreViewModel osztályt a Modellek mappához:
using Microsoft.AspNetCore.Mvc.Rendering;
using System.Collections.Generic;
namespace MvcMovie.Models
{
public class MovieGenreViewModel
{
public List<Movie> Movies { get; set; }
public SelectList Genres { get; set; }
public string MovieGenre { get; set; }
public string SearchString { get; set; }
}
}
A film-műfaj nézetmodell a következőket tartalmazza:
- A filmek listája.
- A műfajok listáját tartalmazó
SelectList. Így a felhasználó kiválaszthat egy műfajt a listából. -
MovieGenre, amely a kiválasztott műfajt tartalmazza. -
SearchString, amely a keresőmezőbe beírt szöveget tartalmazza.
Cserélje le a Index metódust a MoviesController.cs-ban/-ben a következő kódra:
// GET: Movies
public async Task<IActionResult> Index(string movieGenre, string searchString)
{
// 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);
}
var movieGenreVM = new MovieGenreViewModel
{
Genres = new SelectList(await genreQuery.Distinct().ToListAsync()),
Movies = await movies.ToListAsync()
};
return View(movieGenreVM);
}
Az alábbi kód egy LINQ lekérdezés, amely lekéri az összes műfajt az adatbázisból.
// Use LINQ to get list of genres.
IQueryable<string> genreQuery = from m in _context.Movie
orderby m.Genre
select m.Genre;
A műfajok SelectList a különböző műfajok kivetítésével jön létre (nem szeretnénk, hogy a kiválasztási lista duplikált műfajokkal rendelkezzen).
Amikor a felhasználó megkeresi az elemet, a keresési érték megmarad a keresőmezőben.
Keresés hozzáadása műfaj szerint az Index nézethez
A Index.cshtml frissítése megtalálható a Nézetek/Filmek/ alatt az alábbiak szerint:
@model MvcMovie.Models.MovieGenreViewModel
@{
ViewData["Title"] = "Index";
}
<h1>Index</h1>
<p>
<a asp-action="Create">Create New</a>
</p>
<form asp-controller="Movies" asp-action="Index" method="get">
<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">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Movies[0].Title)
</th>
<th>
@Html.DisplayNameFor(model => model.Movies[0].ReleaseDate)
</th>
<th>
@Html.DisplayNameFor(model => model.Movies[0].Genre)
</th>
<th>
@Html.DisplayNameFor(model => model.Movies[0].Price)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.Movies)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.ReleaseDate)
</td>
<td>
@Html.DisplayFor(modelItem => item.Genre)
</td>
<td>
@Html.DisplayFor(modelItem => item.Price)
</td>
<td>
<a asp-action="Edit" asp-route-id="@item.Id">Edit</a> |
<a asp-action="Details" asp-route-id="@item.Id">Details</a> |
<a asp-action="Delete" asp-route-id="@item.Id">Delete</a>
</td>
</tr>
}
</tbody>
</table>
Vizsgálja meg a következő HTML-segédben használt lambda kifejezést:
@Html.DisplayNameFor(model => model.Movies[0].Title)
Az előző kódban a DisplayNameFor HTML-segéd a lambda kifejezésben hivatkozott Title tulajdonságot vizsgálja a megjelenítendő név meghatározásához. Mivel a lambda kifejezést nem kiértékelik, nem kap hozzáférési szabálysértést, ha model, model.Moviesvagy model.Movies[0]null vagy üres. A lambda kifejezés kiértékelésekor (például @Html.DisplayFor(modelItem => item.Title)) a modell tulajdonságértékei lesznek kiértékelve.
Tesztelje az alkalmazást műfaj, filmcím és mindkettő alapján: