Bölüm 7, ASP.NET Core MVC uygulamasına arama ekleme
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.
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 , Contains
veya OrderBy
gibi Where
bir 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.
yönteminin imzasını Index
adlı id
id
bir parametreye sahip olacak şekilde değiştirirseniz, parametresi içinde Program.cs
ayarlanan 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 id
değ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.
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ı searchString
bir 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.
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.
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:
Form verilerini görüntülemek için Ağ ve Yük sekmeleri seçilir:
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.
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.Movies
veya olduğunda veya null
model.Movies[0]
boş olduğunda model
eriş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:
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 , Contains
veya OrderBy
gibi Where
bir 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.
yönteminin imzasını Index
adlı id
id
bir parametreye sahip olacak şekilde değiştirirseniz, parametresi içinde Program.cs
ayarlanan 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 id
değ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.
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ı searchString
bir 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.
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.
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:
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.
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.Movies
veya olduğunda veya null
model.Movies[0]
boş olduğunda model
eriş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:
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 , Contains
veya OrderBy
gibi Where
bir 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.
yönteminin imzasını Index
adlı id
id
bir parametreye sahip olacak şekilde değiştirirseniz, parametresi içinde Program.cs
ayarlanan 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 id
değ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.
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ı searchString
bir 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.
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.
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:
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.
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.Movies
veya olduğunda veya null
model.Movies[0]
boş olduğunda model
eriş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:
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 , Contains
veya OrderBy
gibi Where
bir 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.
yönteminin imzasını Index
adlı id
id
bir parametreye sahip olacak şekilde değiştirirseniz, parametresi içinde Program.cs
ayarlanan 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 id
değ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.
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ı searchString
bir 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.
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.
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:
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.
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.Movies
veya olduğunda veya null
model.Movies[0]
boş olduğunda model
eriş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:
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 , Contains
veya OrderBy
gibi Where
bir 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.
yönteminin imzasını Index
adlı id
id
bir parametreye sahip olacak şekilde değiştirirseniz, parametresi içinde Startup.cs
ayarlanan 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 id
değ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.
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ı searchString
bir 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.
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.
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:
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.
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.Movies
veya olduğunda veya null
model.Movies[0]
boş olduğunda model
eriş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:
ASP.NET Core