Megosztás a következőn keresztül:


7. rész: Keresés hozzáadása egy ASP.NET Core MVC-alkalmazáshoz

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.

Index nézet

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.

Az index nézet, amelyhez a szellem szót hozzáadták az URL-címhez, egy filmlistát tartalmaz, amely két filmet sorol fel: Ghostbusters és Ghostbusters 2.

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.

Index nézet a Címszűrő szövegmezőbe beírt szellem szóval

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.

Böngészőablak a HttpPost Index alkalmazásválaszával: szűrjön a szellem

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.

Chrome böngésző fejlesztői eszközeinek Hálózat és Fejléc lapja, amelyen egy kéréstörzs látható a ghost searchString értékével

A Hálózat és a Terhelési fülek vannak kiválasztva az űrlapadatok megtekintéséhez:

A Chrome böngésző fejlesztői eszközeinek Hálózat és Terhelés lapjai, amelyek űrlapadatokat mutatnak

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.

A böngészőablakban a searchString=ghost jelenik meg az URL-ben, és a visszaadott filmek, a Szellemirtók és a Szellemirtók 2, tartalmazzák a

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:

böngészőablak mutatja a https://localhost:5001/Movies?MovieGenre=Comedy& keresési kifejezés = 2

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.

Index nézet

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.

Az index nézet, amelyhez a szellem szót hozzáadták az URL-címhez, egy filmlistát tartalmaz, amely két filmet sorol fel: Ghostbusters és Ghostbusters 2.

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.

Index nézet a Címszűrő szövegmezőbe beírt szellem szóval

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.

Böngészőablak a HttpPost Index alkalmazásválaszával: szűrjön a szellem

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:

Microsoft Edge fejlesztői eszközeinek Hálózat lapja, amelyen egy kéréstörzs jelenik meg a searchString

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.

A böngészőablakban a searchString=ghost jelenik meg az URL-ben, és a visszaadott filmek, a Szellemirtók és a Szellemirtók 2, tartalmazzák a

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:

böngészőablak mutatja a https://localhost:5001/Movies?MovieGenre=Comedy& keresési kifejezés = 2

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.

Index nézet

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.

Az index nézet, amelyhez a szellem szót hozzáadták az URL-címhez, egy filmlistát tartalmaz, amely két filmet sorol fel: Ghostbusters és Ghostbusters 2.

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.

Index nézet a Címszűrő szövegmezőbe beírt szellem szóval

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.

Böngészőablak a HttpPost Index alkalmazásválaszával: szűrjön a szellem

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:

Microsoft Edge fejlesztői eszközeinek Hálózat lapja, amelyen egy kéréstörzs jelenik meg a searchString

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.

A böngészőablakban a searchString=ghost jelenik meg az URL-ben, és a visszaadott filmek, a Szellemirtók és a Szellemirtók 2, tartalmazzák a

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:

böngészőablak mutatja a https://localhost:5001/Movies?MovieGenre=Comedy& keresési kifejezés = 2

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.

Index nézet

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.

Az index nézet, amelyhez a szellem szót hozzáadták az URL-címhez, egy filmlistát tartalmaz, amely két filmet sorol fel: Ghostbusters és Ghostbusters 2.

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.

Index nézet a Címszűrő szövegmezőbe beírt szellem szóval

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.

Böngészőablak a HttpPost Index alkalmazásválaszával: szűrjön a szellem

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:

Microsoft Edge fejlesztői eszközeinek Hálózat lapja, amelyen egy kéréstörzs jelenik meg a searchString

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.

A böngészőablakban a searchString=ghost jelenik meg az URL-ben, és a visszaadott filmek, a Szellemirtók és a Szellemirtók 2, tartalmazzák a

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:

böngészőablak mutatja a https://localhost:5001/Movies?MovieGenre=Comedy& keresési kifejezés = 2

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.

Index nézet

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.

Az index nézet, amelyhez a szellem szót hozzáadták az URL-címhez, egy filmlistát tartalmaz, amely két filmet sorol fel: Ghostbusters és Ghostbusters 2.

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.

Index nézet a Címszűrő szövegmezőbe beírt szellem szóval

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.

Böngészőablak a HttpPost Index alkalmazásválaszával: szűrjön a szellem

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:

Microsoft Edge fejlesztői eszközeinek Hálózat lapja, amelyen egy kéréstörzs jelenik meg a searchString

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.

A böngészőablakban a searchString=ghost jelenik meg az URL-ben, és a visszaadott filmek, a Szellemirtók és a Szellemirtók 2, tartalmazzák a

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:

böngészőablak mutatja a https://localhost:5001/Movies?MovieGenre=Comedy& keresési kifejezés = 2