Aracılığıyla paylaş


Bölüm 7, ASP.NET Core MVC uygulamasına arama ekleme

Not

Bu, bu makalenin en son sürümü değildir. Geçerli sürüm için bu makalenin .NET 8 sürümüne bakın.

Uyarı

ASP.NET Core'un bu sürümü artık desteklenmiyor. Daha fazla bilgi için bkz . .NET ve .NET Core Destek İlkesi. Geçerli sürüm için bu makalenin .NET 8 sürümüne bakın.

Önemli

Bu bilgiler, ticari olarak piyasaya sürülmeden önce önemli ölçüde değiştirilebilen bir yayın öncesi ürünle ilgilidir. Burada verilen bilgilerle ilgili olarak Microsoft açık veya zımni hiçbir garanti vermez.

Geçerli sürüm için bu makalenin .NET 8 sürümüne bakın.

Gönderen Rick Anderson

Bu bölümde, filmlerde türe veya ada göre arama yapmanızı sağlayan eylem yöntemine arama özelliği Index eklersiniz.

Index içinde Controllers/MoviesController.cs bulunan yöntemini aşağıdaki kodla güncelleştirin:

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

Eylem yöntemindeki Index aşağıdaki satır, filmleri seçmek için bir LINQ sorgusu oluşturur:

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

Sorgu yalnızca bu noktada tanımlanır , veritabanında çalıştırılmaz .

searchString Parametresi bir dize içeriyorsa, filmler sorgusu arama dizesinin değerine göre filtre uygulamak için değiştirilir:

if (!String.IsNullOrEmpty(searchString))
{
    movies = movies.Where(s => s.Title!.ToUpper().Contains(searchString.ToUpper()));
}

s => s.Title!.ToUpper().Contains(searchString.ToUpper()) Yukarıdaki kod bir Lambda İfadesi'dir. Lambda'lar yöntem tabanlı LINQ sorgularında, yöntem veya Contains gibi standart sorgu işleci yöntemlerinin Where bağımsız değişkenleri olarak kullanılır (yukarıdaki kodda kullanılır). LINQ sorguları tanımlandığında veya , Containsveya OrderBygibi Wherebir yöntem çağrılarak değiştirildiğinde yürütülür. Bunun yerine, sorgu yürütme ertelenmiş. Başka bir deyişle, bir ifadenin değerlendirmesi, gerçekleştirilen değeri gerçekten yineleninceye veya yöntemi çağrılana ToListAsync kadar geciktirilir. Ertelenen sorgu yürütme hakkında daha fazla bilgi için bkz . Sorgu Yürütme.

Not

Contains yöntemi C# kodunda değil veritabanında çalıştırılır. Sorgudaki büyük/küçük harf duyarlılığı veritabanına ve harmanlama işlemine bağlıdır. SQL Server'da, Contains büyük/küçük harfe duyarsız olan SQL LIKE ile eşler. Varsayılan harmanlama ile SQLite, sorguya bağlı olarak büyük/küçük harfe duyarlı ve BÜYÜK/küçük harfE DUYARLı bir karışımdır. Büyük/küçük harfe duyarsız SQLite sorguları yapma hakkında bilgi için aşağıdakilere bakın:

Şuraya gidin: /Movies/Index GIBI ?searchString=Ghost bir sorgu dizesini URL'ye ekleyin. Filtrelenen filmler görüntülenir.

Dizin görünümü

yönteminin imzasını Index adlı id idbir parametreye sahip olacak şekilde değiştirirseniz, parametresi içinde Program.csayarlanan varsayılan yollar için isteğe bağlı {id} yer tutucuyla eşleşecektir.

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");

parametresini id olarak değiştirin ve öğesinin searchString tüm oluşumlarını olarak iddeğiştirin.

Yukarıdaki Index yöntemi:

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

parametresiyle id güncelleştirilmiş Index yöntem:

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

Artık arama başlığını sorgu dizesi değeri yerine yönlendirme verileri (URL segmenti) olarak geçirebilirsiniz.

Url'ye hayalet sözcüğünün eklendiği dizin görünümü ve ghostbusters ve Ghostbusters adlı iki filmin döndürülen film listesi 2

Ancak, kullanıcıların bir film için her arama yapmak istediklerinde URL'yi değiştirmelerini bekleyemezsiniz. Bu nedenle artık filmleri filtrelemelerine yardımcı olmak için kullanıcı arabirimi öğeleri ekleyeceksiniz. Yöntemin Index imzasını rotaya bağlı ID parametrenin nasıl geçirildiğini test etmek için değiştirdiyseniz, adlı searchStringbir parametreyi alması için geri değiştirin:

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

Views/Movies/Index.cshtml Dosyayı açın ve aşağıda vurgulanan işaretlemeyi <form> ekleyin:

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

HTML <form> etiketi Form Etiketi Yardımcısı'nı kullandığından, formu gönderdiğinizde filtre dizesi film denetleyicisinin eylemine Index gönderilir. Değişikliklerinizi kaydedin ve filtreyi test edin.

Başlık filtresi metin kutusuna hayalet sözcüğünün yazıldığı dizin görünümü

yönteminde Index beklediğiniz gibi bir aşırı yükleme yoktur[HttpPost]. Yöntem uygulamanın durumunu değiştiremediğinden, yalnızca verileri filtrelediğinden, buna ihtiyacınız yoktur.

Aşağıdaki [HttpPost] Index yöntemi ekleyebilirsiniz.

[HttpPost]
public string Index(string searchString, bool notUsed)
{
    return "From [HttpPost]Index: filter on " + searchString;
}

notUsed parametresi yöntemi için bir aşırı yükleme oluşturmak için Index kullanılır. Öğreticinin ilerleyen bölümlerinde bu konu hakkında konuşacağız.

Bu yöntemi eklerseniz, eylem çağırıcı yöntemiyle [HttpPost] Index eşleşecek ve [HttpPost] Index yöntem aşağıdaki görüntüde gösterildiği gibi çalışacaktır.

HttpPost Dizininden uygulama yanıtı içeren tarayıcı penceresi: hayalete göre filtrele

Ancak, yöntemin Index bu [HttpPost] sürümünü ekleseniz bile, tüm bunların nasıl uygulandığında bir sınırlama vardır. Belirli bir aramaya yer işareti eklemek istediğinizi veya aynı filtrelenmiş film listesini görmek için tıklayabilecekleri arkadaşlarınıza bir bağlantı göndermek istediğinizi düşünün. HTTP POST isteğinin URL'sinin GET isteğinin URL'si (localhost:{PORT}/Movies/Index) ile aynı olduğuna dikkat edin; URL'de arama bilgisi yoktur. Arama dizesi bilgileri sunucuya bir form alanı değeri olarak gönderilir. Bunu tarayıcı Geliştirici araçları veya mükemmel Fiddler aracıyla doğrulayabilirsiniz.

Aşağıdaki görüntüde Ağ ve Üst Bilgiler sekmelerinin seçili olduğu Chrome tarayıcısı Geliştirici araçları gösterilmektedir:

Chrome tarayıcısı Geliştirici Araçları'nın searchString değeri hayalet olan bir istek gövdesini gösteren Ağ ve Üst Bilgiler sekmeleri

Form verilerini görüntülemek için Ağ ve Yük sekmeleri seçilir:

Form verilerini gösteren Chrome tarayıcısı Geliştirici Araçları'nın Ağ ve Yük sekmeleri

arama parametresini ve XSRF belirtecini istek gövdesinde görebilirsiniz. Önceki öğreticide belirtildiği gibi, Form Etiketi Yardımcısı bir XSRF sahteciliği önleme belirteci oluşturur. Verileri değiştirmiyoruz, bu nedenle denetleyici yönteminde belirteci doğrulamamız gerekmez.

Arama parametresi URL'de değil istek gövdesinde olduğundan, yer işareti eklemek veya başkalarıyla paylaşmak için bu arama bilgilerini yakalayamazsınız. İsteğin dosyada bulunan etikette form olması HTTP GET gerektiğini belirterek bunu düzeltinViews/Movies/Index.cshtml.

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

Artık bir arama gönderdiğinizde, URL arama sorgusu dizesini içerir. Arama, bir HttpPost Index yönteminiz olsa bile eylem yöntemine HttpGet Index de gider.

Url'de searchString=ghost öğesini gösteren tarayıcı penceresi ve döndürülen filmler, Ghostbusters ve Ghostbusters 2, hayalet sözcüğünü içerir

Türe göre Arama Ekle

Models klasörüne aşağıdaki MovieGenreViewModel sınıfı ekleyin:

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

Film tarzı görünüm modeli aşağıdakileri içerir:

  • Film listesi.
  • SelectList Türlerin listesini içeren. Bu, kullanıcının listeden bir tür seçmesine olanak tanır.
  • MovieGenre, seçili türü içerir.
  • SearchString, kullanıcıların arama metin kutusuna girdiği metni içerir.

Index içindeki MoviesController.cs yöntemini aşağıdaki kodla değiştirin:

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

Aşağıdaki kod, veritabanından tüm türleri alan bir LINQ sorgudur.

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

Türlerin SelectList türü, farklı türlerin yansıtılmasıyla oluşturulur (seçme listemizin yinelenen tarzlara sahip olmasını istemeyiz).

Kullanıcı öğeyi ararken, arama değeri arama kutusunda tutulur.

Dizin görünümüne türe göre arama ekleme

Görünümler/Filmler/'de bulunan güncelleştirme Index.cshtml aşağıdaki gibi:

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

Aşağıdaki HTML Yardımcısı'nda kullanılan lambda ifadesini inceleyin:

@Html.DisplayNameFor(model => model.Movies![0].Title)

Önceki kodda DisplayNameFor , HTML Yardımcısı görünen adı belirlemek için lambda ifadesinde başvuruda bulunan özelliği inceler Title . Lambda ifadesi değerlendirilmek yerine incelendiğinden, , model.Moviesveya olduğunda veya null model.Movies[0] boş olduğunda modelerişim ihlali almazsınız. Lambda ifadesi değerlendirildiğinde (örneğin, @Html.DisplayFor(modelItem => item.Title)), modelin özellik değerleri değerlendirilir. after!, null olmadığını bildirmek Movies için kullanılan null-forgiving işlecidir.model.Movies

Türe, film başlığına ve her ikisine göre arama yaparak uygulamayı test edin:

sonuçlarını gösteren https://localhost:5001/Movies?MovieGenre=Comedy&amptarayıcı penceresi; SearchString=2

Bu bölümde, filmlerde türe veya ada göre arama yapmanızı sağlayan eylem yöntemine arama özelliği Index eklersiniz.

Index içinde Controllers/MoviesController.cs bulunan yöntemini aşağıdaki kodla güncelleştirin:

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

Eylem yöntemindeki Index aşağıdaki satır, filmleri seçmek için bir LINQ sorgusu oluşturur:

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

Sorgu yalnızca bu noktada tanımlanır , veritabanında çalıştırılmaz .

searchString Parametresi bir dize içeriyorsa, filmler sorgusu arama dizesinin değerine göre filtre uygulamak için değiştirilir:

if (!String.IsNullOrEmpty(searchString))
{
    movies = movies.Where(s => s.Title!.ToUpper().Contains(searchString.ToUpper()));
}

s => s.Title!.ToUpper().Contains(searchString.ToUpper()) Yukarıdaki kod bir Lambda İfadesi'dir. Lambda'lar yöntem tabanlı LINQ sorgularında, yöntem veya Contains gibi standart sorgu işleci yöntemlerinin Where bağımsız değişkenleri olarak kullanılır (yukarıdaki kodda kullanılır). LINQ sorguları tanımlandığında veya , Containsveya OrderBygibi Wherebir yöntem çağrılarak değiştirildiğinde yürütülür. Bunun yerine, sorgu yürütme ertelenmiş. Başka bir deyişle, bir ifadenin değerlendirmesi, gerçekleştirilen değeri gerçekten yineleninceye veya yöntemi çağrılana ToListAsync kadar geciktirilir. Ertelenen sorgu yürütme hakkında daha fazla bilgi için bkz . Sorgu Yürütme.

Not

Contains yöntemi C# kodunda değil veritabanında çalıştırılır. Sorgudaki büyük/küçük harf duyarlılığı veritabanına ve harmanlama işlemine bağlıdır. SQL Server'da, Contains büyük/küçük harfe duyarsız olan SQL LIKE ile eşler. Varsayılan harmanlama ile SQLite, sorguya bağlı olarak büyük/küçük harfe duyarlı ve BÜYÜK/küçük harfE DUYARLı bir karışımdır. Büyük/küçük harfe duyarsız SQLite sorguları yapma hakkında bilgi için aşağıdakilere bakın:

Şuraya gidin: /Movies/Index GIBI ?searchString=Ghost bir sorgu dizesini URL'ye ekleyin. Filtrelenen filmler görüntülenir.

Dizin görünümü

yönteminin imzasını Index adlı id idbir parametreye sahip olacak şekilde değiştirirseniz, parametresi içinde Program.csayarlanan varsayılan yollar için isteğe bağlı {id} yer tutucuyla eşleşecektir.

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");

parametresini id olarak değiştirin ve öğesinin searchString tüm oluşumlarını olarak iddeğiştirin.

Yukarıdaki Index yöntemi:

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

parametresiyle id güncelleştirilmiş Index yöntem:

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

Artık arama başlığını sorgu dizesi değeri yerine yönlendirme verileri (URL segmenti) olarak geçirebilirsiniz.

Url'ye hayalet sözcüğünün eklendiği dizin görünümü ve ghostbusters ve Ghostbusters adlı iki filmin döndürülen film listesi 2

Ancak, kullanıcıların bir film için her arama yapmak istediklerinde URL'yi değiştirmelerini bekleyemezsiniz. Bu nedenle artık filmleri filtrelemelerine yardımcı olmak için kullanıcı arabirimi öğeleri ekleyeceksiniz. Yöntemin Index imzasını rotaya bağlı ID parametrenin nasıl geçirildiğini test etmek için değiştirdiyseniz, adlı searchStringbir parametreyi alması için geri değiştirin:

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

Views/Movies/Index.cshtml Dosyayı açın ve aşağıda vurgulanan işaretlemeyi <form> ekleyin:

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

HTML <form> etiketi Form Etiketi Yardımcısı'nı kullandığından, formu gönderdiğinizde filtre dizesi film denetleyicisinin eylemine Index gönderilir. Değişikliklerinizi kaydedin ve filtreyi test edin.

Başlık filtresi metin kutusuna hayalet sözcüğünün yazıldığı dizin görünümü

yönteminde Index beklediğiniz gibi bir aşırı yükleme yoktur[HttpPost]. Yöntem uygulamanın durumunu değiştiremediğinden, yalnızca verileri filtrelediğinden, buna ihtiyacınız yoktur.

Aşağıdaki [HttpPost] Index yöntemi ekleyebilirsiniz.

[HttpPost]
public string Index(string searchString, bool notUsed)
{
    return "From [HttpPost]Index: filter on " + searchString;
}

notUsed parametresi yöntemi için bir aşırı yükleme oluşturmak için Index kullanılır. Öğreticinin ilerleyen bölümlerinde bu konu hakkında konuşacağız.

Bu yöntemi eklerseniz, eylem çağırıcı yöntemiyle [HttpPost] Index eşleşecek ve [HttpPost] Index yöntem aşağıdaki görüntüde gösterildiği gibi çalışacaktır.

HttpPost Dizininden uygulama yanıtı içeren tarayıcı penceresi: hayalete göre filtrele

Ancak, yöntemin Index bu [HttpPost] sürümünü ekleseniz bile, tüm bunların nasıl uygulandığında bir sınırlama vardır. Belirli bir aramaya yer işareti eklemek istediğinizi veya aynı filtrelenmiş film listesini görmek için tıklayabilecekleri arkadaşlarınıza bir bağlantı göndermek istediğinizi düşünün. HTTP POST isteğinin URL'sinin GET isteğinin URL'si (localhost:{PORT}/Movies/Index) ile aynı olduğuna dikkat edin; URL'de arama bilgisi yoktur. Arama dizesi bilgileri sunucuya bir form alanı değeri olarak gönderilir. Bunu tarayıcı Geliştirici araçları veya mükemmel Fiddler aracıyla doğrulayabilirsiniz. Aşağıdaki görüntüde Chrome tarayıcı Geliştirici araçları gösterilmektedir:

Microsoft Edge Geliştirici Araçları'nın searchString değeri hayalet olan bir istek gövdesini gösteren ağ sekmesi

arama parametresini ve XSRF belirtecini istek gövdesinde görebilirsiniz. Önceki öğreticide belirtildiği gibi, Form Etiketi Yardımcısı bir XSRF sahteciliği önleme belirteci oluşturur. Verileri değiştirmiyoruz, bu nedenle denetleyici yönteminde belirteci doğrulamamız gerekmez.

Arama parametresi URL'de değil istek gövdesinde olduğundan, yer işareti eklemek veya başkalarıyla paylaşmak için bu arama bilgilerini yakalayamazsınız. İsteğin dosyada bulunması gerektiğini HTTP GET belirterek bunu düzeltin Views/Movies/Index.cshtml .

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

Artık bir arama gönderdiğinizde, URL arama sorgusu dizesini içerir. Arama, bir HttpPost Index yönteminiz olsa bile eylem yöntemine HttpGet Index de gider.

Url'de searchString=ghost öğesini gösteren tarayıcı penceresi ve döndürülen filmler, Ghostbusters ve Ghostbusters 2, hayalet sözcüğünü içerir

Aşağıdaki işaretleme etiketindeki değişikliği form gösterir:

<form asp-controller="Movies" asp-action="Index" method="get">

Türe göre Arama Ekle

Models klasörüne aşağıdaki MovieGenreViewModel sınıfı ekleyin:

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

Film tarzı görünüm modeli aşağıdakileri içerir:

  • Film listesi.
  • SelectList Türlerin listesini içeren. Bu, kullanıcının listeden bir tür seçmesine olanak tanır.
  • MovieGenre, seçili türü içerir.
  • SearchString, kullanıcıların arama metin kutusuna girdiği metni içerir.

Index içindeki MoviesController.cs yöntemini aşağıdaki kodla değiştirin:

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

Aşağıdaki kod, veritabanından tüm türleri alan bir LINQ sorgudur.

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

Türlerin SelectList türü, farklı türlerin yansıtılmasıyla oluşturulur (seçme listemizin yinelenen tarzlara sahip olmasını istemeyiz).

Kullanıcı öğeyi ararken, arama değeri arama kutusunda tutulur.

Dizin görünümüne türe göre arama ekleme

Görünümler/Filmler/'de bulunan güncelleştirme Index.cshtml aşağıdaki gibi:

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

Aşağıdaki HTML Yardımcısı'nda kullanılan lambda ifadesini inceleyin:

@Html.DisplayNameFor(model => model.Movies![0].Title)

Önceki kodda DisplayNameFor , HTML Yardımcısı görünen adı belirlemek için lambda ifadesinde başvuruda bulunan özelliği inceler Title . Lambda ifadesi değerlendirilmek yerine incelendiğinden, , model.Moviesveya olduğunda veya null model.Movies[0] boş olduğunda modelerişim ihlali almazsınız. Lambda ifadesi değerlendirildiğinde (örneğin, @Html.DisplayFor(modelItem => item.Title)), modelin özellik değerleri değerlendirilir. after!, null olmadığını bildirmek Movies için kullanılan null-forgiving işlecidir.model.Movies

Türe, film başlığına ve her ikisine göre arama yaparak uygulamayı test edin:

sonuçlarını gösteren https://localhost:5001/Movies?MovieGenre=Comedy&amptarayıcı penceresi; SearchString=2

Bu bölümde, filmlerde türe veya ada göre arama yapmanızı sağlayan eylem yöntemine arama özelliği Index eklersiniz.

Index içinde Controllers/MoviesController.cs bulunan yöntemini aşağıdaki kodla güncelleştirin:

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

Eylem yöntemindeki Index aşağıdaki satır, filmleri seçmek için bir LINQ sorgusu oluşturur:

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

Sorgu yalnızca bu noktada tanımlanır , veritabanında çalıştırılmaz .

searchString Parametresi bir dize içeriyorsa, filmler sorgusu arama dizesinin değerine göre filtre uygulamak için değiştirilir:

if (!String.IsNullOrEmpty(searchString))
{
    movies = movies.Where(s => s.Title!.ToUpper().Contains(searchString.ToUpper()));
}

s => s.Title!.ToUpper().Contains(searchString.ToUpper()) Yukarıdaki kod bir Lambda İfadesi'dir. Lambda'lar yöntem tabanlı LINQ sorgularında, yöntem veya Contains gibi standart sorgu işleci yöntemlerinin Where bağımsız değişkenleri olarak kullanılır (yukarıdaki kodda kullanılır). LINQ sorguları tanımlandığında veya , Containsveya OrderBygibi Wherebir yöntem çağrılarak değiştirildiğinde yürütülür. Bunun yerine, sorgu yürütme ertelenmiş. Başka bir deyişle, bir ifadenin değerlendirmesi, gerçekleştirilen değeri gerçekten yineleninceye veya yöntemi çağrılana ToListAsync kadar geciktirilir. Ertelenen sorgu yürütme hakkında daha fazla bilgi için bkz . Sorgu Yürütme.

Not

Contains yöntemi C# kodunda değil veritabanında çalıştırılır. Sorgudaki büyük/küçük harf duyarlılığı veritabanına ve harmanlama işlemine bağlıdır. SQL Server'da, Contains büyük/küçük harfe duyarsız olan SQL LIKE ile eşler. Varsayılan harmanlama ile SQLite, sorguya bağlı olarak büyük/küçük harfe duyarlı ve BÜYÜK/küçük harfE DUYARLı bir karışımdır. Büyük/küçük harfe duyarsız SQLite sorguları yapma hakkında bilgi için aşağıdakilere bakın:

Şuraya gidin: /Movies/Index GIBI ?searchString=Ghost bir sorgu dizesini URL'ye ekleyin. Filtrelenen filmler görüntülenir.

Dizin görünümü

yönteminin imzasını Index adlı id idbir parametreye sahip olacak şekilde değiştirirseniz, parametresi içinde Program.csayarlanan varsayılan yollar için isteğe bağlı {id} yer tutucuyla eşleşecektir.

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");

parametresini id olarak değiştirin ve öğesinin searchString tüm oluşumlarını olarak iddeğiştirin.

Yukarıdaki Index yöntemi:

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

parametresiyle id güncelleştirilmiş Index yöntem:

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

Artık arama başlığını sorgu dizesi değeri yerine yönlendirme verileri (URL segmenti) olarak geçirebilirsiniz.

Url'ye hayalet sözcüğünün eklendiği dizin görünümü ve ghostbusters ve Ghostbusters adlı iki filmin döndürülen film listesi 2

Ancak, kullanıcıların bir film için her arama yapmak istediklerinde URL'yi değiştirmelerini bekleyemezsiniz. Bu nedenle artık filmleri filtrelemelerine yardımcı olmak için kullanıcı arabirimi öğeleri ekleyeceksiniz. Yöntemin Index imzasını rotaya bağlı ID parametrenin nasıl geçirildiğini test etmek için değiştirdiyseniz, adlı searchStringbir parametreyi alması için geri değiştirin:

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

Views/Movies/Index.cshtml Dosyayı açın ve aşağıda vurgulanan işaretlemeyi <form> ekleyin:

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

HTML <form> etiketi Form Etiketi Yardımcısı'nı kullandığından, formu gönderdiğinizde filtre dizesi film denetleyicisinin eylemine Index gönderilir. Değişikliklerinizi kaydedin ve filtreyi test edin.

Başlık filtresi metin kutusuna hayalet sözcüğünün yazıldığı dizin görünümü

yönteminde Index beklediğiniz gibi bir aşırı yükleme yoktur[HttpPost]. Yöntem uygulamanın durumunu değiştiremediğinden, yalnızca verileri filtrelediğinden, buna ihtiyacınız yoktur.

Aşağıdaki [HttpPost] Index yöntemi ekleyebilirsiniz.

[HttpPost]
public string Index(string searchString, bool notUsed)
{
    return "From [HttpPost]Index: filter on " + searchString;
}

notUsed parametresi yöntemi için bir aşırı yükleme oluşturmak için Index kullanılır. Öğreticinin ilerleyen bölümlerinde bu konu hakkında konuşacağız.

Bu yöntemi eklerseniz, eylem çağırıcı yöntemiyle [HttpPost] Index eşleşecek ve [HttpPost] Index yöntem aşağıdaki görüntüde gösterildiği gibi çalışacaktır.

HttpPost Dizininden uygulama yanıtı içeren tarayıcı penceresi: hayalete göre filtrele

Ancak, yöntemin Index bu [HttpPost] sürümünü ekleseniz bile, tüm bunların nasıl uygulandığında bir sınırlama vardır. Belirli bir aramaya yer işareti eklemek istediğinizi veya aynı filtrelenmiş film listesini görmek için tıklayabilecekleri arkadaşlarınıza bir bağlantı göndermek istediğinizi düşünün. HTTP POST isteğinin URL'sinin GET isteğinin URL'si (localhost:{PORT}/Movies/Index) ile aynı olduğuna dikkat edin; URL'de arama bilgisi yoktur. Arama dizesi bilgileri sunucuya bir form alanı değeri olarak gönderilir. Bunu tarayıcı Geliştirici araçları veya mükemmel Fiddler aracıyla doğrulayabilirsiniz. Aşağıdaki görüntüde Chrome tarayıcı Geliştirici araçları gösterilmektedir:

Microsoft Edge Geliştirici Araçları'nın searchString değeri hayalet olan bir istek gövdesini gösteren ağ sekmesi

arama parametresini ve XSRF belirtecini istek gövdesinde görebilirsiniz. Önceki öğreticide belirtildiği gibi, Form Etiketi Yardımcısı bir XSRF sahteciliği önleme belirteci oluşturur. Verileri değiştirmiyoruz, bu nedenle denetleyici yönteminde belirteci doğrulamamız gerekmez.

Arama parametresi URL'de değil istek gövdesinde olduğundan, yer işareti eklemek veya başkalarıyla paylaşmak için bu arama bilgilerini yakalayamazsınız. İsteğin dosyada bulunması gerektiğini HTTP GET belirterek bunu düzeltin Views/Movies/Index.cshtml .

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

Artık bir arama gönderdiğinizde, URL arama sorgusu dizesini içerir. Arama, bir HttpPost Index yönteminiz olsa bile eylem yöntemine HttpGet Index de gider.

Url'de searchString=ghost öğesini gösteren tarayıcı penceresi ve döndürülen filmler, Ghostbusters ve Ghostbusters 2, hayalet sözcüğünü içerir

Aşağıdaki işaretleme etiketindeki değişikliği form gösterir:

<form asp-controller="Movies" asp-action="Index" method="get">

Türe göre Arama Ekle

Models klasörüne aşağıdaki MovieGenreViewModel sınıfı ekleyin:

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

Film tarzı görünüm modeli aşağıdakileri içerir:

  • Film listesi.
  • SelectList Türlerin listesini içeren. Bu, kullanıcının listeden bir tür seçmesine olanak tanır.
  • MovieGenre, seçili türü içerir.
  • SearchString, kullanıcıların arama metin kutusuna girdiği metni içerir.

Index içindeki MoviesController.cs yöntemini aşağıdaki kodla değiştirin:

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

Aşağıdaki kod, veritabanından tüm türleri alan bir LINQ sorgudur.

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

Türlerin SelectList türü, farklı türlerin yansıtılmasıyla oluşturulur (seçme listemizin yinelenen tarzlara sahip olmasını istemeyiz).

Kullanıcı öğeyi ararken, arama değeri arama kutusunda tutulur.

Dizin görünümüne türe göre arama ekleme

Görünümler/Filmler/'de bulunan güncelleştirme Index.cshtml aşağıdaki gibi:

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

Aşağıdaki HTML Yardımcısı'nda kullanılan lambda ifadesini inceleyin:

@Html.DisplayNameFor(model => model.Movies![0].Title)

Önceki kodda DisplayNameFor , HTML Yardımcısı görünen adı belirlemek için lambda ifadesinde başvuruda bulunan özelliği inceler Title . Lambda ifadesi değerlendirilmek yerine incelendiğinden, , model.Moviesveya olduğunda veya null model.Movies[0] boş olduğunda modelerişim ihlali almazsınız. Lambda ifadesi değerlendirildiğinde (örneğin, @Html.DisplayFor(modelItem => item.Title)), modelin özellik değerleri değerlendirilir. after!, null olmadığını bildirmek Movies için kullanılan null-forgiving işlecidir.model.Movies

Türe, film başlığına ve her ikisine göre arama yaparak uygulamayı test edin:

sonuçlarını gösteren https://localhost:5001/Movies?MovieGenre=Comedy&amptarayıcı penceresi; SearchString=2

Bu bölümde, filmlerde türe veya ada göre arama yapmanızı sağlayan eylem yöntemine arama özelliği Index eklersiniz.

Index içinde Controllers/MoviesController.cs bulunan yöntemini aşağıdaki kodla güncelleştirin:

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

Eylem yönteminin Index ilk satırı, filmleri seçmek için bir LINQ sorgusu oluşturur:

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

Sorgu yalnızca bu noktada tanımlanır , veritabanında çalıştırılmaz .

searchString Parametresi bir dize içeriyorsa, filmler sorgusu arama dizesinin değerine göre filtre uygulamak için değiştirilir:

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

s => s.Title!.Contains(searchString) Yukarıdaki kod bir Lambda İfadesi'dir. Lambda'lar yöntem tabanlı LINQ sorgularında, yöntem veya Contains gibi standart sorgu işleci yöntemlerinin Where bağımsız değişkenleri olarak kullanılır (yukarıdaki kodda kullanılır). LINQ sorguları tanımlandığında veya , Containsveya OrderBygibi Wherebir yöntem çağrılarak değiştirildiğinde yürütülür. Bunun yerine, sorgu yürütme ertelenmiş. Başka bir deyişle, bir ifadenin değerlendirmesi, gerçekleştirilen değeri gerçekten yineleninceye veya yöntemi çağrılana ToListAsync kadar geciktirilir. Ertelenen sorgu yürütme hakkında daha fazla bilgi için bkz . Sorgu Yürütme.

Not: Contains Yöntemi, yukarıda gösterilen c# kodunda değil veritabanında çalıştırılır. Sorgudaki büyük/küçük harf duyarlılığı veritabanına ve harmanlama işlemine bağlıdır. SQL Server'da, Contains büyük/küçük harfe duyarsız olan SQL LIKE ile eşler. SQLite'te varsayılan harmanlama ile büyük/küçük harfe duyarlıdır.

Şuraya gidin: /Movies/Index GIBI ?searchString=Ghost bir sorgu dizesini URL'ye ekleyin. Filtrelenen filmler görüntülenir.

Dizin görünümü

yönteminin imzasını Index adlı id idbir parametreye sahip olacak şekilde değiştirirseniz, parametresi içinde Program.csayarlanan varsayılan yollar için isteğe bağlı {id} yer tutucuyla eşleşecektir.

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");

parametresini id olarak değiştirin ve öğesinin searchString tüm oluşumlarını olarak iddeğiştirin.

Yukarıdaki Index yöntemi:

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

parametresiyle id güncelleştirilmiş Index yöntem:

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

Artık arama başlığını sorgu dizesi değeri yerine yönlendirme verileri (URL segmenti) olarak geçirebilirsiniz.

Url'ye hayalet sözcüğünün eklendiği dizin görünümü ve ghostbusters ve Ghostbusters adlı iki filmin döndürülen film listesi 2

Ancak, kullanıcıların bir film için her arama yapmak istediklerinde URL'yi değiştirmelerini bekleyemezsiniz. Bu nedenle artık filmleri filtrelemelerine yardımcı olmak için kullanıcı arabirimi öğeleri ekleyeceksiniz. Yöntemin Index imzasını rotaya bağlı ID parametrenin nasıl geçirildiğini test etmek için değiştirdiyseniz, adlı searchStringbir parametreyi alması için geri değiştirin:

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

Views/Movies/Index.cshtml Dosyayı açın ve aşağıda vurgulanan işaretlemeyi <form> ekleyin:

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

HTML <form> etiketi Form Etiketi Yardımcısı'nı kullandığından, formu gönderdiğinizde filtre dizesi film denetleyicisinin eylemine Index gönderilir. Değişikliklerinizi kaydedin ve filtreyi test edin.

Başlık filtresi metin kutusuna hayalet sözcüğünün yazıldığı dizin görünümü

yönteminde Index beklediğiniz gibi bir aşırı yükleme yoktur[HttpPost]. Yöntem uygulamanın durumunu değiştiremediğinden, yalnızca verileri filtrelediğinden, buna ihtiyacınız yoktur.

Aşağıdaki [HttpPost] Index yöntemi ekleyebilirsiniz.

[HttpPost]
public string Index(string searchString, bool notUsed)
{
    return "From [HttpPost]Index: filter on " + searchString;
}

notUsed parametresi yöntemi için bir aşırı yükleme oluşturmak için Index kullanılır. Öğreticinin ilerleyen bölümlerinde bu konu hakkında konuşacağız.

Bu yöntemi eklerseniz, eylem çağırıcı yöntemiyle [HttpPost] Index eşleşecek ve [HttpPost] Index yöntem aşağıdaki görüntüde gösterildiği gibi çalışacaktır.

HttpPost Dizininden uygulama yanıtı içeren tarayıcı penceresi: hayalete göre filtrele

Ancak, yöntemin Index bu [HttpPost] sürümünü ekleseniz bile, tüm bunların nasıl uygulandığında bir sınırlama vardır. Belirli bir aramaya yer işareti eklemek istediğinizi veya aynı filtrelenmiş film listesini görmek için tıklayabilecekleri arkadaşlarınıza bir bağlantı göndermek istediğinizi düşünün. HTTP POST isteğinin URL'sinin GET isteğinin URL'si (localhost:{PORT}/Movies/Index) ile aynı olduğuna dikkat edin; URL'de arama bilgisi yoktur. Arama dizesi bilgileri sunucuya bir form alanı değeri olarak gönderilir. Bunu tarayıcı Geliştirici araçları veya mükemmel Fiddler aracıyla doğrulayabilirsiniz. Aşağıdaki görüntüde Chrome tarayıcı Geliştirici araçları gösterilmektedir:

Microsoft Edge Geliştirici Araçları'nın searchString değeri hayalet olan bir istek gövdesini gösteren ağ sekmesi

arama parametresini ve XSRF belirtecini istek gövdesinde görebilirsiniz. Önceki öğreticide belirtildiği gibi, Form Etiketi Yardımcısı bir XSRF sahteciliği önleme belirteci oluşturur. Verileri değiştirmiyoruz, bu nedenle denetleyici yönteminde belirteci doğrulamamız gerekmez.

Arama parametresi URL'de değil istek gövdesinde olduğundan, yer işareti eklemek veya başkalarıyla paylaşmak için bu arama bilgilerini yakalayamazsınız. İsteğin dosyada bulunması gerektiğini HTTP GET belirterek bunu düzeltin Views/Movies/Index.cshtml .

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

Artık bir arama gönderdiğinizde, URL arama sorgusu dizesini içerir. Arama, bir HttpPost Index yönteminiz olsa bile eylem yöntemine HttpGet Index de gider.

Url'de searchString=ghost öğesini gösteren tarayıcı penceresi ve döndürülen filmler, Ghostbusters ve Ghostbusters 2, hayalet sözcüğünü içerir

Aşağıdaki işaretleme etiketindeki değişikliği form gösterir:

<form asp-controller="Movies" asp-action="Index" method="get">

Türe göre Arama Ekle

Models klasörüne aşağıdaki MovieGenreViewModel sınıfı ekleyin:

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

Film tarzı görünüm modeli aşağıdakileri içerir:

  • Film listesi.
  • SelectList Türlerin listesini içeren. Bu, kullanıcının listeden bir tür seçmesine olanak tanır.
  • MovieGenre, seçili türü içerir.
  • SearchString, kullanıcıların arama metin kutusuna girdiği metni içerir.

Index içindeki MoviesController.cs yöntemini aşağıdaki kodla değiştirin:

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

Aşağıdaki kod, veritabanından tüm türleri alan bir LINQ sorgudur.

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

Türlerin SelectList türü, farklı türlerin yansıtılmasıyla oluşturulur (seçme listemizin yinelenen tarzlara sahip olmasını istemeyiz).

Kullanıcı öğeyi ararken, arama değeri arama kutusunda tutulur.

Dizin görünümüne türe göre arama ekleme

Görünümler/Filmler/'de bulunan güncelleştirme Index.cshtml aşağıdaki gibi:

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

Aşağıdaki HTML Yardımcısı'nda kullanılan lambda ifadesini inceleyin:

@Html.DisplayNameFor(model => model.Movies[0].Title)

Önceki kodda DisplayNameFor , HTML Yardımcısı görünen adı belirlemek için lambda ifadesinde başvuruda bulunan özelliği inceler Title . Lambda ifadesi değerlendirilmek yerine incelendiğinden, , model.Moviesveya olduğunda veya null model.Movies[0] boş olduğunda modelerişim ihlali almazsınız. Lambda ifadesi değerlendirildiğinde (örneğin, @Html.DisplayFor(modelItem => item.Title)), modelin özellik değerleri değerlendirilir.

Türe, film başlığına ve her ikisine göre arama yaparak uygulamayı test edin:

sonuçlarını gösteren https://localhost:5001/Movies?MovieGenre=Comedy&amptarayıcı penceresi; SearchString=2

Bu bölümde, filmlerde türe veya ada göre arama yapmanızı sağlayan eylem yöntemine arama özelliği Index eklersiniz.

Index içinde Controllers/MoviesController.cs bulunan yöntemini aşağıdaki kodla güncelleştirin:

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

Eylem yönteminin Index ilk satırı, filmleri seçmek için bir LINQ sorgusu oluşturur:

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

Sorgu yalnızca bu noktada tanımlanır, veritabanında çalıştırılmaz .

searchString Parametresi bir dize içeriyorsa, filmler sorgusu arama dizesinin değerine göre filtre uygulamak için değiştirilir:

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

s => s.Title.Contains() Yukarıdaki kod bir Lambda İfadesi'dir. Lambda'lar yöntem tabanlı LINQ sorgularında, yöntem veya Contains gibi standart sorgu işleci yöntemlerinin Where bağımsız değişkenleri olarak kullanılır (yukarıdaki kodda kullanılır). LINQ sorguları tanımlandığında veya , Containsveya OrderBygibi Wherebir yöntem çağrılarak değiştirildiğinde yürütülür. Bunun yerine, sorgu yürütme ertelenmiş. Başka bir deyişle, bir ifadenin değerlendirmesi, gerçekleştirilen değeri gerçekten yineleninceye veya yöntemi çağrılana ToListAsync kadar geciktirilir. Ertelenen sorgu yürütme hakkında daha fazla bilgi için bkz . Sorgu Yürütme.

Not: Contains Yöntemi, yukarıda gösterilen c# kodunda değil veritabanında çalıştırılır. Sorgudaki büyük/küçük harf duyarlılığı veritabanına ve harmanlama işlemine bağlıdır. SQL Server'da, Contains büyük/küçük harfe duyarsız olan SQL LIKE ile eşler. SQLite'te varsayılan harmanlama ile büyük/küçük harfe duyarlıdır.

Şuraya gidin: /Movies/Index GIBI ?searchString=Ghost bir sorgu dizesini URL'ye ekleyin. Filtrelenen filmler görüntülenir.

Dizin görünümü

yönteminin imzasını Index adlı id idbir parametreye sahip olacak şekilde değiştirirseniz, parametresi içinde Startup.csayarlanan varsayılan yollar için isteğe bağlı {id} yer tutucuyla eşleşecektir.

app.UseEndpoints(endpoints =>
{
    endpoints.MapControllerRoute(
        name: "default",
        pattern: "{controller=Home}/{action=Index}/{id?}");
});

parametresini id olarak değiştirin ve değişikliğin searchString tüm oluşumlarını olarak iddeğiştirin.

Yukarıdaki Index yöntemi:

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

parametresiyle id güncelleştirilmiş Index yöntem:

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

Artık arama başlığını sorgu dizesi değeri yerine yönlendirme verileri (URL segmenti) olarak geçirebilirsiniz.

Url'ye hayalet sözcüğünün eklendiği dizin görünümü ve ghostbusters ve Ghostbusters adlı iki filmin döndürülen film listesi 2

Ancak, kullanıcıların bir film için her arama yapmak istediklerinde URL'yi değiştirmelerini bekleyemezsiniz. Bu nedenle artık filmleri filtrelemelerine yardımcı olmak için kullanıcı arabirimi öğeleri ekleyeceksiniz. Yöntemin Index imzasını rotaya bağlı ID parametrenin nasıl geçirildiğini test etmek için değiştirdiyseniz, adlı searchStringbir parametreyi alması için geri değiştirin:

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

Views/Movies/Index.cshtml Dosyayı açın ve aşağıda vurgulanan işaretlemeyi <form> ekleyin:

    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>

HTML <form> etiketi Form Etiketi Yardımcısı'nı kullandığından, formu gönderdiğinizde filtre dizesi film denetleyicisinin eylemine Index gönderilir. Değişikliklerinizi kaydedin ve filtreyi test edin.

Başlık filtresi metin kutusuna hayalet sözcüğünün yazıldığı dizin görünümü

yönteminde Index beklediğiniz gibi bir aşırı yükleme yoktur[HttpPost]. Yöntem uygulamanın durumunu değiştiremediğinden, yalnızca verileri filtrelediğinden, buna ihtiyacınız yoktur.

Aşağıdaki [HttpPost] Index yöntemi ekleyebilirsiniz.

[HttpPost]
public string Index(string searchString, bool notUsed)
{
    return "From [HttpPost]Index: filter on " + searchString;
}

notUsed parametresi yöntemi için bir aşırı yükleme oluşturmak için Index kullanılır. Öğreticinin ilerleyen bölümlerinde bu konu hakkında konuşacağız.

Bu yöntemi eklerseniz, eylem çağırıcı yöntemiyle [HttpPost] Index eşleşecek ve [HttpPost] Index yöntem aşağıdaki görüntüde gösterildiği gibi çalışacaktır.

HttpPost Dizininden uygulama yanıtı içeren tarayıcı penceresi: hayalete göre filtrele

Ancak, yöntemin Index bu [HttpPost] sürümünü ekleseniz bile, tüm bunların nasıl uygulandığında bir sınırlama vardır. Belirli bir aramaya yer işareti eklemek istediğinizi veya aynı filtrelenmiş film listesini görmek için tıklayabilecekleri arkadaşlarınıza bir bağlantı göndermek istediğinizi düşünün. HTTP POST isteğinin URL'sinin GET isteğinin URL'si (localhost:{PORT}/Movies/Index) ile aynı olduğuna dikkat edin; URL'de arama bilgisi yoktur. Arama dizesi bilgileri sunucuya bir form alanı değeri olarak gönderilir. Bunu tarayıcı Geliştirici araçları veya mükemmel Fiddler aracıyla doğrulayabilirsiniz. Aşağıdaki görüntüde Chrome tarayıcı Geliştirici araçları gösterilmektedir:

Microsoft Edge Geliştirici Araçları'nın searchString değeri hayalet olan bir istek gövdesini gösteren ağ sekmesi

arama parametresini ve XSRF belirtecini istek gövdesinde görebilirsiniz. Önceki öğreticide belirtildiği gibi, Form Etiketi Yardımcısı bir XSRF sahteciliği önleme belirteci oluşturur. Verileri değiştirmiyoruz, bu nedenle denetleyici yönteminde belirteci doğrulamamız gerekmez.

Arama parametresi URL'de değil istek gövdesinde olduğundan, yer işareti eklemek veya başkalarıyla paylaşmak için bu arama bilgilerini yakalayamazsınız. İsteğin dosyada bulunması gerektiğini HTTP GET belirterek bunu düzeltin Views/Movies/Index.cshtml .

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

Artık bir arama gönderdiğinizde, URL arama sorgusu dizesini içerir. Arama, bir HttpPost Index yönteminiz olsa bile eylem yöntemine HttpGet Index de gider.

Url'de searchString=ghost öğesini gösteren tarayıcı penceresi ve döndürülen filmler, Ghostbusters ve Ghostbusters 2, hayalet sözcüğünü içerir

Aşağıdaki işaretleme etiketindeki değişikliği form gösterir:

<form asp-controller="Movies" asp-action="Index" method="get">

Türe göre Arama Ekle

Models klasörüne aşağıdaki MovieGenreViewModel sınıfı ekleyin:

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

Film tarzı görünüm modeli aşağıdakileri içerir:

  • Film listesi.
  • SelectList Türlerin listesini içeren. Bu, kullanıcının listeden bir tür seçmesine olanak tanır.
  • MovieGenre, seçili türü içerir.
  • SearchString, kullanıcıların arama metin kutusuna girdiği metni içerir.

Index içindeki MoviesController.cs yöntemini aşağıdaki kodla değiştirin:

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

Aşağıdaki kod, veritabanından tüm türleri alan bir LINQ sorgudur.

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

Türlerin SelectList türü, farklı türlerin yansıtılmasıyla oluşturulur (seçme listemizin yinelenen tarzlara sahip olmasını istemeyiz).

Kullanıcı öğeyi ararken, arama değeri arama kutusunda tutulur.

Dizin görünümüne türe göre arama ekleme

Görünümler/Filmler/'de bulunan güncelleştirme Index.cshtml aşağıdaki gibi:

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

Aşağıdaki HTML Yardımcısı'nda kullanılan lambda ifadesini inceleyin:

@Html.DisplayNameFor(model => model.Movies[0].Title)

Önceki kodda DisplayNameFor , HTML Yardımcısı görünen adı belirlemek için lambda ifadesinde başvuruda bulunan özelliği inceler Title . Lambda ifadesi değerlendirilmek yerine incelendiğinden, , model.Moviesveya olduğunda veya null model.Movies[0] boş olduğunda modelerişim ihlali almazsınız. Lambda ifadesi değerlendirildiğinde (örneğin, @Html.DisplayFor(modelItem => item.Title)), modelin özellik değerleri değerlendirilir.

Türe, film başlığına ve her ikisine göre arama yaparak uygulamayı test edin:

sonuçlarını gösteren https://localhost:5001/Movies?MovieGenre=Comedy&amptarayıcı penceresi; SearchString=2