Часть 6. Добавление поиска в Razor Pages в ASP.NET Core
Примечание.
Это не последняя версия этой статьи. В текущем выпуске см . версию .NET 9 этой статьи.
Предупреждение
Эта версия ASP.NET Core больше не поддерживается. Дополнительные сведения см. в политике поддержки .NET и .NET Core. В текущем выпуске см . версию .NET 9 этой статьи.
Внимание
Эта информация относится к предварительному выпуску продукта, который может быть существенно изменен до его коммерческого выпуска. Майкрософт не предоставляет никаких гарантий, явных или подразумеваемых, относительно приведенных здесь сведений.
В текущем выпуске см . версию .NET 9 этой статьи.
Автор: Рик Андерсон (Rick Anderson)
В следующих разделах добавляется поиск фильмов по жанру или имени.
Добавьте выделенный ниже код в Pages/Movies/Index.cshtml.cs
:
public class IndexModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
public IList<Movie> Movie { get;set; } = default!;
[BindProperty(SupportsGet = true)]
public string? SearchString { get; set; }
public SelectList? Genres { get; set; }
[BindProperty(SupportsGet = true)]
public string? MovieGenre { get; set; }
В предыдущем коде:
SearchString
: содержит текстовые пользователи, вводимые в текстовое поле поиска.SearchString
также имеет атрибут[BindProperty]
.[BindProperty]
связывает значения из формы и строки запроса с тем же именем, что и у свойства.[BindProperty(SupportsGet = true)]
требуется для привязки в запросах HTTP GET.Genres
: содержит список жанров.Genres
дает пользователю возможность выбрать жанр в списке. ДляSelectList
требуетсяusing Microsoft.AspNetCore.Mvc.Rendering;
.MovieGenre
: содержит определенный жанр, который выбирает пользователь. Например, "Боевик".Genres
иMovieGenre
рассматриваются позднее в этом учебнике.
Предупреждение
В целях безопасности вам следует задать привязку данных запроса GET
к свойствам страничной модели. Проверьте введенные данные пользователя, прежде чем сопоставлять их со свойствами. Привязка GET
полезна при обращении к сценариям, использующим строку запроса или значения маршрутов.
Чтобы привязать свойство к запросам GET
, задайте для свойства SupportsGet
атрибута [BindProperty]
значение true
:
[BindProperty(SupportsGet = true)]
Дополнительные сведения: ASP.NET Core Community Standup: Bind on GET discussion (YouTube).
Обновите метод OnGetAsync
страницы Movies/Index
, используя следующий код:
public async Task OnGetAsync()
{
var movies = from m in _context.Movie
select m;
if (!string.IsNullOrEmpty(SearchString))
{
movies = movies.Where(s => s.Title.Contains(SearchString));
}
Movie = await movies.ToListAsync();
}
В первой строке метода OnGetAsync
создается запрос LINQ для выбора фильмов:
var movies = from m in _context.Movie
select m;
Этот запрос только определяется в этой точке и не выполняется для базы данных.
SearchString
Если свойство не null
является или пусто, запрос фильмов изменяется для фильтрации в строке поиска:
if (!string.IsNullOrEmpty(SearchString))
{
movies = movies.Where(s => s.Title.Contains(SearchString));
}
Код s => s.Title.Contains()
представляет собой лямбда-выражение. Лямбда-выражения используются в запросах LINQ на основе методов в качестве аргументов стандартных методов операторов запроса, таких как метод Where или Contains
. Запросы LINQ не выполняются, если они определяются или изменяются путем вызова метода, например Where
, Contains
или OrderBy
. Вместо этого выполнение запроса откладывается. Вычисление выражения откладывается до тех пор, пока не будет выполнена итерация его реализованного значения или не будет вызван метод ToListAsync
. Дополнительные сведения см. в разделе Выполнение запроса.
Примечание.
Метод Contains выполняется в базе данных, а не в коде C#. Регистр символов запроса учитывается в зависимости от параметров базы данных и сортировки. В SQL Server метод Contains
сопоставляется с SQL LIKE, в котором регистр символов не учитывается. SQLite с параметрами сортировки по умолчанию — это смесь параметров с учетом регистра и параметров, которые НЕ учитывают регистр, в зависимости от запроса. Сведения о том, как выполнять запросы SQLite, которые не учитывают регистр, см. в следующих статьях:
Перейдите на страницу Movies и добавьте строку запроса, например ?searchString=Ghost
, к URL-адресу. Например, https://localhost:5001/Movies?searchString=Ghost
. Отображаются отфильтрованные фильмы.
Если на страницу Index добавлен следующий шаблон маршрута, строку поиска можно передать в виде сегмента URL-адреса. Например, https://localhost:5001/Movies/Ghost
.
@page "{searchString?}"
Предыдущее ограничение маршрута разрешало поиск названия в виде данных маршрута (сегмент URL-адреса) вместо значения строки запроса. Символ ?
в "{searchString?}"
означает, что этот параметр является необязательным.
Среда выполнения ASP.NET Core использует привязку модели, чтобы присвоить значение свойства SearchString
по строке запроса (?searchString=Ghost
) или данным маршрута (https://localhost:5001/Movies/Ghost
). Привязка модели не учитывает регистр символов.
Однако пользователи не могут изменять URL-адрес для поиска фильма. На этом шаге добавляется пользовательский интерфейс для поиска фильмов. Если было добавлено ограничение маршрута "{searchString?}"
, удалите его.
Откройте файл Pages/Movies/Index.cshtml
и добавьте разметку, которая выделена в следующем коде:
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@{
ViewData["Title"] = "Index";
}
<h1>Index</h1>
<p>
<a asp-page="Create">Create New</a>
</p>
<form>
<p>
<label>Title: <input type="text" asp-for="SearchString" /></label>
<input type="submit" value="Filter" />
</p>
</form>
<table class="table">
<thead>
Тег HTML <form>
использует следующие вспомогательные функции тегов:
- вспомогательная функция тега форм. При отправке формы строка фильтра отправляется на страницу Pages/Movies/Index в строке запроса.
- Вспомогательная функция тега Input
Сохраните изменения и проверьте работу фильтра.
Поиск по жанру
Movies/Index.cshtml.cs
Обновите метод страницы OnGetAsync
следующим кодом:
public async Task OnGetAsync()
{
// <snippet_search_linqQuery>
IQueryable<string> genreQuery = from m in _context.Movie
orderby m.Genre
select m.Genre;
// </snippet_search_linqQuery>
var movies = from m in _context.Movie
select m;
if (!string.IsNullOrEmpty(SearchString))
{
movies = movies.Where(s => s.Title.Contains(SearchString));
}
if (!string.IsNullOrEmpty(MovieGenre))
{
movies = movies.Where(x => x.Genre == MovieGenre);
}
// <snippet_search_selectList>
Genres = new SelectList(await genreQuery.Distinct().ToListAsync());
// </snippet_search_selectList>
Movie = await movies.ToListAsync();
}
Следующий код определяет запрос LINQ, который извлекает все жанры из базы данных.
IQueryable<string> genreQuery = from m in _context.Movie
orderby m.Genre
select m.Genre;
Жанры SelectList
создаются путем проецирования различных жанров:
Genres = new SelectList(await genreQuery.Distinct().ToListAsync());
Добавление поиска по жанру на страницу Razor
Обновите элемент, как выделено в следующей<form>
Index.cshtml
разметке:
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@{
ViewData["Title"] = "Index";
}
<h1>Index</h1>
<p>
<a asp-page="Create">Create New</a>
</p>
<form>
<p>
<select asp-for="MovieGenre" asp-items="Model.Genres">
<option value="">All</option>
</select>
<label>Title: <input type="text" asp-for="SearchString" /></label>
<input type="submit" value="Filter" />
</p>
</form>
Проверьте работу приложения, выполнив поиск по жанру, по названию фильма и по обоим этим параметрам:
Следующие шаги
В следующих разделах добавляется поиск фильмов по жанру или имени.
Добавьте выделенный ниже код в Pages/Movies/Index.cshtml.cs
:
public class IndexModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
public IList<Movie> Movie { get;set; } = default!;
[BindProperty(SupportsGet = true)]
public string? SearchString { get; set; }
public SelectList? Genres { get; set; }
[BindProperty(SupportsGet = true)]
public string? MovieGenre { get; set; }
В предыдущем коде:
SearchString
: содержит текстовые пользователи, вводимые в текстовое поле поиска.SearchString
также имеет атрибут[BindProperty]
.[BindProperty]
связывает значения из формы и строки запроса с тем же именем, что и у свойства.[BindProperty(SupportsGet = true)]
требуется для привязки в запросах HTTP GET.Genres
: содержит список жанров.Genres
дает пользователю возможность выбрать жанр в списке. ДляSelectList
требуетсяusing Microsoft.AspNetCore.Mvc.Rendering;
.MovieGenre
: содержит определенный жанр, который выбирает пользователь. Например, "Боевик".Genres
иMovieGenre
рассматриваются позднее в этом учебнике.
Предупреждение
В целях безопасности вам следует задать привязку данных запроса GET
к свойствам страничной модели. Проверьте введенные данные пользователя, прежде чем сопоставлять их со свойствами. Привязка GET
полезна при обращении к сценариям, использующим строку запроса или значения маршрутов.
Чтобы привязать свойство к запросам GET
, задайте для свойства SupportsGet
атрибута [BindProperty]
значение true
:
[BindProperty(SupportsGet = true)]
Дополнительные сведения: ASP.NET Core Community Standup: Bind on GET discussion (YouTube).
Обновите метод OnGetAsync
страницы Index, добавив следующий код:
public async Task OnGetAsync()
{
var movies = from m in _context.Movie
select m;
if (!string.IsNullOrEmpty(SearchString))
{
movies = movies.Where(s => s.Title.Contains(SearchString));
}
Movie = await movies.ToListAsync();
}
В первой строке метода OnGetAsync
создается запрос LINQ для выбора фильмов:
// using System.Linq;
var movies = from m in _context.Movie
select m;
Этот запрос только определяется в этой точке и не выполняется для базы данных.
SearchString
Если свойство не null
является или пусто, запрос фильмов изменяется для фильтрации в строке поиска:
if (!string.IsNullOrEmpty(SearchString))
{
movies = movies.Where(s => s.Title.Contains(SearchString));
}
Код s => s.Title.Contains()
представляет собой лямбда-выражение. Лямбда-выражения используются в запросах LINQ на основе методов в качестве аргументов стандартных методов операторов запроса, таких как метод Where или Contains
. Запросы LINQ не выполняются, если они определяются или изменяются путем вызова метода, например Where
, Contains
или OrderBy
. Вместо этого выполнение запроса откладывается. Вычисление выражения откладывается до тех пор, пока не будет выполнена итерация его реализованного значения или не будет вызван метод ToListAsync
. Дополнительные сведения см. в разделе Выполнение запроса.
Примечание.
Метод Contains выполняется в базе данных, а не в коде C#. Регистр символов запроса учитывается в зависимости от параметров базы данных и сортировки. В SQL Server метод Contains
сопоставляется с SQL LIKE, в котором регистр символов не учитывается. SQLite с параметрами сортировки по умолчанию — это смесь параметров с учетом регистра и параметров, которые НЕ учитывают регистр, в зависимости от запроса. Сведения о том, как выполнять запросы SQLite, которые не учитывают регистр, см. в следующих статьях:
Перейдите на страницу Movies и добавьте строку запроса, например ?searchString=Ghost
, к URL-адресу. Например, https://localhost:5001/Movies?searchString=Ghost
. Отображаются отфильтрованные фильмы.
Если на страницу Index добавлен следующий шаблон маршрута, строку поиска можно передать в виде сегмента URL-адреса. Например, https://localhost:5001/Movies/Ghost
.
@page "{searchString?}"
Предыдущее ограничение маршрута разрешало поиск названия в виде данных маршрута (сегмент URL-адреса) вместо значения строки запроса. Символ ?
в "{searchString?}"
означает, что этот параметр является необязательным.
Среда выполнения ASP.NET Core использует привязку модели, чтобы присвоить значение свойства SearchString
по строке запроса (?searchString=Ghost
) или данным маршрута (https://localhost:5001/Movies/Ghost
). Привязка модели не учитывает регистр символов.
Однако пользователи не могут изменять URL-адрес для поиска фильма. На этом шаге добавляется пользовательский интерфейс для поиска фильмов. Если было добавлено ограничение маршрута "{searchString?}"
, удалите его.
Откройте файл Pages/Movies/Index.cshtml
и добавьте разметку, которая выделена в следующем коде:
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@{
ViewData["Title"] = "Index";
}
<h1>Index</h1>
<p>
<a asp-page="Create">Create New</a>
</p>
<form>
<p>
<label>Title: <input type="text" asp-for="SearchString" /></label>
<input type="submit" value="Filter" />
</p>
</form>
<table class="table">
@*Markup removed for brevity.*@
Тег HTML <form>
использует следующие вспомогательные функции тегов:
- вспомогательная функция тега форм. При отправке формы строка фильтра отправляется на страницу Pages/Movies/Index в строке запроса.
- Вспомогательная функция тега Input
Сохраните изменения и проверьте работу фильтра.
Поиск по жанру
Movies/Index.cshtml.cs
Обновите метод страницы OnGetAsync
следующим кодом:
public async Task OnGetAsync()
{
// Use LINQ to get list of genres.
IQueryable<string> genreQuery = from m in _context.Movie
orderby m.Genre
select m.Genre;
var movies = from m in _context.Movie
select m;
if (!string.IsNullOrEmpty(SearchString))
{
movies = movies.Where(s => s.Title.Contains(SearchString));
}
if (!string.IsNullOrEmpty(MovieGenre))
{
movies = movies.Where(x => x.Genre == MovieGenre);
}
Genres = new SelectList(await genreQuery.Distinct().ToListAsync());
Movie = await movies.ToListAsync();
}
Следующий код определяет запрос LINQ, который извлекает все жанры из базы данных.
// Use LINQ to get list of genres.
IQueryable<string> genreQuery = from m in _context.Movie
orderby m.Genre
select m.Genre;
Список жанров SelectList
создается путем проецирования отдельных жанров.
Genres = new SelectList(await genreQuery.Distinct().ToListAsync());
Добавление поиска по жанру на страницу Razor
Обновите элемент, как выделено в следующей<form>
Index.cshtml
разметке:
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@{
ViewData["Title"] = "Index";
}
<h1>Index</h1>
<p>
<a asp-page="Create">Create New</a>
</p>
<form>
<p>
<select asp-for="MovieGenre" asp-items="Model.Genres">
<option value="">All</option>
</select>
<label>Title: <input type="text" asp-for="SearchString" /></label>
<input type="submit" value="Filter" />
</p>
</form>
Проверьте работу приложения, выполнив поиск по жанру, по названию фильма и по обоим этим параметрам.
Следующие шаги
В следующих разделах добавляется поиск фильмов по жанру или имени.
Добавьте выделенный ниже код в Pages/Movies/Index.cshtml.cs
:
public class IndexModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
public IList<Movie> Movie { get;set; } = default!;
[BindProperty(SupportsGet = true)]
public string? SearchString { get; set; }
public SelectList? Genres { get; set; }
[BindProperty(SupportsGet = true)]
public string? MovieGenre { get; set; }
В предыдущем коде:
SearchString
: содержит текстовые пользователи, вводимые в текстовое поле поиска.SearchString
также имеет атрибут[BindProperty]
.[BindProperty]
связывает значения из формы и строки запроса с тем же именем, что и у свойства.[BindProperty(SupportsGet = true)]
требуется для привязки в запросах HTTP GET.Genres
: содержит список жанров.Genres
дает пользователю возможность выбрать жанр в списке. ДляSelectList
требуетсяusing Microsoft.AspNetCore.Mvc.Rendering;
.MovieGenre
: содержит определенный жанр, который выбирает пользователь. Например, "Боевик".Genres
иMovieGenre
рассматриваются позднее в этом учебнике.
Предупреждение
В целях безопасности вам следует задать привязку данных запроса GET
к свойствам страничной модели. Проверьте введенные данные пользователя, прежде чем сопоставлять их со свойствами. Привязка GET
полезна при обращении к сценариям, использующим строку запроса или значения маршрутов.
Чтобы привязать свойство к запросам GET
, задайте для свойства SupportsGet
атрибута [BindProperty]
значение true
:
[BindProperty(SupportsGet = true)]
Дополнительные сведения: ASP.NET Core Community Standup: Bind on GET discussion (YouTube).
Обновите метод OnGetAsync
страницы Index, добавив следующий код:
public async Task OnGetAsync()
{
var movies = from m in _context.Movie
select m;
if (!string.IsNullOrEmpty(SearchString))
{
movies = movies.Where(s => s.Title.Contains(SearchString));
}
Movie = await movies.ToListAsync();
}
В первой строке метода OnGetAsync
создается запрос LINQ для выбора фильмов:
// using System.Linq;
var movies = from m in _context.Movie
select m;
Этот запрос только определяется в этой точке и не выполняется для базы данных.
SearchString
Если свойство не null
является или пусто, запрос фильмов изменяется для фильтрации в строке поиска:
if (!string.IsNullOrEmpty(SearchString))
{
movies = movies.Where(s => s.Title.Contains(SearchString));
}
Код s => s.Title.Contains()
представляет собой лямбда-выражение. Лямбда-выражения используются в запросах LINQ на основе методов в качестве аргументов стандартных методов операторов запроса, таких как метод Where или Contains
. Запросы LINQ не выполняются, если они определяются или изменяются путем вызова метода, например Where
, Contains
или OrderBy
. Вместо этого выполнение запроса откладывается. Вычисление выражения откладывается до тех пор, пока не будет выполнена итерация его реализованного значения или не будет вызван метод ToListAsync
. Дополнительные сведения см. в разделе Выполнение запроса.
Примечание.
Метод Contains выполняется в базе данных, а не в коде C#. Регистр символов запроса учитывается в зависимости от параметров базы данных и сортировки. В SQL Server метод Contains
сопоставляется с SQL LIKE, в котором регистр символов не учитывается. SQLite с параметрами сортировки по умолчанию — это смесь параметров с учетом регистра и параметров, которые НЕ учитывают регистр, в зависимости от запроса. Сведения о том, как выполнять запросы SQLite, которые не учитывают регистр, см. в следующих статьях:
Перейдите на страницу Movies и добавьте строку запроса, например ?searchString=Ghost
, к URL-адресу. Например, https://localhost:5001/Movies?searchString=Ghost
. Отображаются отфильтрованные фильмы.
Если на страницу Index добавлен следующий шаблон маршрута, строку поиска можно передать в виде сегмента URL-адреса. Например, https://localhost:5001/Movies/Ghost
.
@page "{searchString?}"
Предыдущее ограничение маршрута разрешало поиск названия в виде данных маршрута (сегмент URL-адреса) вместо значения строки запроса. Символ ?
в "{searchString?}"
означает, что этот параметр является необязательным.
Среда выполнения ASP.NET Core использует привязку модели, чтобы присвоить значение свойства SearchString
по строке запроса (?searchString=Ghost
) или данным маршрута (https://localhost:5001/Movies/Ghost
). Привязка модели не учитывает регистр символов.
Однако пользователи не могут изменять URL-адрес для поиска фильма. На этом шаге добавляется пользовательский интерфейс для поиска фильмов. Если было добавлено ограничение маршрута "{searchString?}"
, удалите его.
Откройте файл Pages/Movies/Index.cshtml
и добавьте разметку, которая выделена в следующем коде:
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@{
ViewData["Title"] = "Index";
}
<h1>Index</h1>
<p>
<a asp-page="Create">Create New</a>
</p>
<form>
<p>
<label>Title: <input type="text" asp-for="SearchString" /></label>
<input type="submit" value="Filter" />
</p>
</form>
<table class="table">
@*Markup removed for brevity.*@
Тег HTML <form>
использует следующие вспомогательные функции тегов:
- вспомогательная функция тега форм. При отправке формы строка фильтра отправляется на страницу Pages/Movies/Index в строке запроса.
- Вспомогательная функция тега Input
Сохраните изменения и проверьте работу фильтра.
Поиск по жанру
Обновите метод OnGetAsync
страницы Index, добавив следующий код:
public async Task OnGetAsync()
{
// Use LINQ to get list of genres.
IQueryable<string> genreQuery = from m in _context.Movie
orderby m.Genre
select m.Genre;
var movies = from m in _context.Movie
select m;
if (!string.IsNullOrEmpty(SearchString))
{
movies = movies.Where(s => s.Title.Contains(SearchString));
}
if (!string.IsNullOrEmpty(MovieGenre))
{
movies = movies.Where(x => x.Genre == MovieGenre);
}
Genres = new SelectList(await genreQuery.Distinct().ToListAsync());
Movie = await movies.ToListAsync();
}
Следующий код определяет запрос LINQ, который извлекает все жанры из базы данных.
// Use LINQ to get list of genres.
IQueryable<string> genreQuery = from m in _context.Movie
orderby m.Genre
select m.Genre;
Список жанров SelectList
создается путем проецирования отдельных жанров.
Genres = new SelectList(await genreQuery.Distinct().ToListAsync());
Добавление поиска по жанру на страницу Razor
Обновите элемент, как выделено в следующей<form>
Index.cshtml
разметке:
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@{
ViewData["Title"] = "Index";
}
<h1>Index</h1>
<p>
<a asp-page="Create">Create New</a>
</p>
<form>
<p>
<select asp-for="MovieGenre" asp-items="Model.Genres">
<option value="">All</option>
</select>
<label>Title: <input type="text" asp-for="SearchString" /></label>
<input type="submit" value="Filter" />
</p>
</form>
Проверьте работу приложения, выполнив поиск по жанру, по названию фильма и по обоим этим параметрам.
Следующие шаги
В следующих разделах добавляется поиск фильмов по жанру или имени.
Добавьте выделенный ниже код в Pages/Movies/Index.cshtml.cs
:
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
using RazorPagesMovie.Models;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace RazorPagesMovie.Pages.Movies
{
public class IndexModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
public IList<Movie> Movie { get;set; } = default!;
[BindProperty(SupportsGet = true)]
public string ? SearchString { get; set; }
public SelectList ? Genres { get; set; }
[BindProperty(SupportsGet = true)]
public string ? MovieGenre { get; set; }
В предыдущем коде:
SearchString
: содержит текстовые пользователи, вводимые в текстовое поле поиска.SearchString
также имеет атрибут[BindProperty]
.[BindProperty]
связывает значения из формы и строки запроса с тем же именем, что и у свойства.[BindProperty(SupportsGet = true)]
требуется для привязки в запросах HTTP GET.Genres
: содержит список жанров.Genres
дает пользователю возможность выбрать жанр в списке. ДляSelectList
требуетсяusing Microsoft.AspNetCore.Mvc.Rendering;
.MovieGenre
: содержит определенный жанр, который выбирает пользователь. Например, "Боевик".Genres
иMovieGenre
рассматриваются позднее в этом учебнике.
Предупреждение
В целях безопасности вам следует задать привязку данных запроса GET
к свойствам страничной модели. Проверьте введенные данные пользователя, прежде чем сопоставлять их со свойствами. Привязка GET
полезна при обращении к сценариям, использующим строку запроса или значения маршрутов.
Чтобы привязать свойство к запросам GET
, задайте для свойства SupportsGet
атрибута [BindProperty]
значение true
:
[BindProperty(SupportsGet = true)]
Дополнительные сведения: ASP.NET Core Community Standup: Bind on GET discussion (YouTube).
Обновите метод OnGetAsync
страницы Index, добавив следующий код:
public async Task OnGetAsync()
{
var movies = from m in _context.Movie
select m;
if (!string.IsNullOrEmpty(SearchString))
{
movies = movies.Where(s => s.Title.Contains(SearchString));
}
Movie = await movies.ToListAsync();
}
В первой строке метода OnGetAsync
создается запрос LINQ для выбора фильмов:
// using System.Linq;
var movies = from m in _context.Movie
select m;
Этот запрос только определяется в этой точке и не выполняется для базы данных.
Если свойство SearchString
не равно NULL и не пусто, запрос фильмов изменяется для фильтрации по строке поиска:
if (!string.IsNullOrEmpty(SearchString))
{
movies = movies.Where(s => s.Title.Contains(SearchString));
}
Код s => s.Title.Contains()
представляет собой лямбда-выражение. Лямбда-выражения используются в запросах LINQ на основе методов в качестве аргументов стандартных методов операторов запроса, таких как метод Where или Contains
. Запросы LINQ не выполняются, если они определяются или изменяются путем вызова метода, например Where
, Contains
или OrderBy
. Вместо этого выполнение запроса откладывается. Вычисление выражения откладывается до тех пор, пока не будет выполнена итерация его реализованного значения или не будет вызван метод ToListAsync
. Дополнительные сведения см. в разделе Выполнение запроса.
Примечание.
Метод Contains выполняется в базе данных, а не в коде C#. Регистр символов запроса учитывается в зависимости от параметров базы данных и сортировки. В SQL Server метод Contains
сопоставляется с SQL LIKE, в котором регистр символов не учитывается. SQLite с параметрами сортировки по умолчанию — это смесь параметров с учетом регистра и параметров, которые НЕ учитывают регистр, в зависимости от запроса. Сведения о том, как выполнять запросы SQLite, которые не учитывают регистр, см. в следующих статьях:
Перейдите на страницу Movies и добавьте строку запроса, например ?searchString=Ghost
, к URL-адресу. Например, https://localhost:5001/Movies?searchString=Ghost
. Отображаются отфильтрованные фильмы.
Если на страницу Index добавлен следующий шаблон маршрута, строку поиска можно передать в виде сегмента URL-адреса. Например, https://localhost:5001/Movies/Ghost
.
@page "{searchString?}"
Предыдущее ограничение маршрута разрешало поиск названия в виде данных маршрута (сегмент URL-адреса) вместо значения строки запроса. Символ ?
в "{searchString?}"
означает, что этот параметр является необязательным.
Среда выполнения ASP.NET Core использует привязку модели, чтобы присвоить значение свойства SearchString
по строке запроса (?searchString=Ghost
) или данным маршрута (https://localhost:5001/Movies/Ghost
). Привязка модели не учитывает регистр символов.
Однако пользователи не могут изменять URL-адрес для поиска фильма. На этом шаге добавляется пользовательский интерфейс для поиска фильмов. Если было добавлено ограничение маршрута "{searchString?}"
, удалите его.
Откройте файл Pages/Movies/Index.cshtml
и добавьте разметку, которая выделена в следующем коде:
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@{
ViewData["Title"] = "Index";
}
<h1>Index</h1>
<p>
<a asp-page="Create">Create New</a>
</p>
<form>
<p>
<label>Title: <input type="text" asp-for="SearchString" /></label>
<input type="submit" value="Filter" />
</p>
</form>
<table class="table">
@*Markup removed for brevity.*@
Тег HTML <form>
использует следующие вспомогательные функции тегов:
- вспомогательная функция тега форм. При отправке формы строка фильтра отправляется на страницу Pages/Movies/Index в строке запроса.
- Вспомогательная функция тега Input
Сохраните изменения и проверьте работу фильтра.
Поиск по жанру
Обновите метод OnGetAsync
страницы Index, добавив следующий код:
public async Task OnGetAsync()
{
// Use LINQ to get list of genres.
IQueryable<string> genreQuery = from m in _context.Movie
orderby m.Genre
select m.Genre;
var movies = from m in _context.Movie
select m;
if (!string.IsNullOrEmpty(SearchString))
{
movies = movies.Where(s => s.Title.Contains(SearchString));
}
if (!string.IsNullOrEmpty(MovieGenre))
{
movies = movies.Where(x => x.Genre == MovieGenre);
}
Genres = new SelectList(await genreQuery.Distinct().ToListAsync());
Movie = await movies.ToListAsync();
}
Следующий код определяет запрос LINQ, который извлекает все жанры из базы данных.
// Use LINQ to get list of genres.
IQueryable<string> genreQuery = from m in _context.Movie
orderby m.Genre
select m.Genre;
Список жанров SelectList
создается путем проецирования отдельных жанров.
Genres = new SelectList(await genreQuery.Distinct().ToListAsync());
Добавление поиска по жанру на страницу Razor
Обновите элемент, как выделено в следующей<form>
Index.cshtml
разметке:
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@{
ViewData["Title"] = "Index";
}
<h1>Index</h1>
<p>
<a asp-page="Create">Create New</a>
</p>
<form>
<p>
<select asp-for="MovieGenre" asp-items="Model.Genres">
<option value="">All</option>
</select>
<label>Title: <input type="text" asp-for="SearchString" /></label>
<input type="submit" value="Filter" />
</p>
</form>
Проверьте работу приложения, выполнив поиск по жанру, по названию фильма и по обоим этим параметрам.
Следующие шаги
В следующих разделах добавляется поиск фильмов по жанру или имени.
Добавьте следующие выделенные инструкцию using и свойства в Pages/Movies/Index.cshtml.cs
:
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
using RazorPagesMovie.Models;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace RazorPagesMovie.Pages.Movies
{
public class IndexModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
public IList<Movie> Movie { get; set; }
[BindProperty(SupportsGet = true)]
public string SearchString { get; set; }
public SelectList Genres { get; set; }
[BindProperty(SupportsGet = true)]
public string MovieGenre { get; set; }
В предыдущем коде:
SearchString
: содержит текстовые пользователи, вводимые в текстовое поле поиска.SearchString
также имеет атрибут[BindProperty]
.[BindProperty]
связывает значения из формы и строки запроса с тем же именем, что и у свойства.[BindProperty(SupportsGet = true)]
требуется для привязки в запросах HTTP GET.Genres
: содержит список жанров.Genres
дает пользователю возможность выбрать жанр в списке. ДляSelectList
требуетсяusing Microsoft.AspNetCore.Mvc.Rendering;
.MovieGenre
: содержит определенный жанр, который выбирает пользователь. Например, "Боевик".Genres
иMovieGenre
рассматриваются позднее в этом учебнике.
Предупреждение
В целях безопасности вам следует задать привязку данных запроса GET
к свойствам страничной модели. Проверьте введенные данные пользователя, прежде чем сопоставлять их со свойствами. Привязка GET
полезна при обращении к сценариям, использующим строку запроса или значения маршрутов.
Чтобы привязать свойство к запросам GET
, задайте для свойства SupportsGet
атрибута [BindProperty]
значение true
:
[BindProperty(SupportsGet = true)]
Дополнительные сведения: ASP.NET Core Community Standup: Bind on GET discussion (YouTube).
Обновите метод OnGetAsync
страницы Index, добавив следующий код:
public async Task OnGetAsync()
{
var movies = from m in _context.Movie
select m;
if (!string.IsNullOrEmpty(SearchString))
{
movies = movies.Where(s => s.Title.Contains(SearchString));
}
Movie = await movies.ToListAsync();
}
В первой строке метода OnGetAsync
создается запрос LINQ для выбора фильмов:
// using System.Linq;
var movies = from m in _context.Movie
select m;
Этот запрос только определяется в этой точке и не выполняется для базы данных.
Если свойство SearchString
не равно NULL и не пусто, запрос фильмов изменяется для фильтрации по строке поиска:
if (!string.IsNullOrEmpty(SearchString))
{
movies = movies.Where(s => s.Title.Contains(SearchString));
}
Код s => s.Title.Contains()
представляет собой лямбда-выражение. Лямбда-выражения используются в запросах LINQ на основе методов в качестве аргументов стандартных методов операторов запроса, таких как метод Where или Contains
. Запросы LINQ не выполняются, если они определяются или изменяются путем вызова метода, например Where
, Contains
или OrderBy
. Вместо этого выполнение запроса откладывается. Вычисление выражения откладывается до тех пор, пока не будет выполнена итерация его реализованного значения или не будет вызван метод ToListAsync
. Дополнительные сведения см. в разделе Выполнение запроса.
Примечание.
Метод Contains выполняется в базе данных, а не в коде C#. Регистр символов запроса учитывается в зависимости от параметров базы данных и сортировки. В SQL Server метод Contains
сопоставляется с SQL LIKE, в котором регистр символов не учитывается. SQLite с параметрами сортировки по умолчанию — это смесь параметров с учетом регистра и параметров, которые НЕ учитывают регистр, в зависимости от запроса. Сведения о том, как выполнять запросы SQLite, которые не учитывают регистр, см. в следующих статьях:
Перейдите на страницу Movies и добавьте строку запроса, например ?searchString=Ghost
, к URL-адресу. Например, https://localhost:5001/Movies?searchString=Ghost
. Отображаются отфильтрованные фильмы.
Если на страницу Index добавлен следующий шаблон маршрута, строку поиска можно передать в виде сегмента URL-адреса. Например, https://localhost:5001/Movies/Ghost
.
@page "{searchString?}"
Предыдущее ограничение маршрута разрешало поиск названия в виде данных маршрута (сегмент URL-адреса) вместо значения строки запроса. Символ ?
в "{searchString?}"
означает, что этот параметр является необязательным.
Среда выполнения ASP.NET Core использует привязку модели, чтобы присвоить значение свойства SearchString
по строке запроса (?searchString=Ghost
) или данным маршрута (https://localhost:5001/Movies/Ghost
). Привязка модели не учитывает регистр символов.
Однако пользователи не могут изменять URL-адрес для поиска фильма. На этом шаге добавляется пользовательский интерфейс для поиска фильмов. Если было добавлено ограничение маршрута "{searchString?}"
, удалите его.
Откройте файл Pages/Movies/Index.cshtml
и добавьте разметку, которая выделена в следующем коде:
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@{
ViewData["Title"] = "Index";
}
<h1>Index</h1>
<p>
<a asp-page="Create">Create New</a>
</p>
<form>
<p>
<label>Title: <input type="text" asp-for="SearchString" /></label>
<input type="submit" value="Filter" />
</p>
</form>
<table class="table">
@*Markup removed for brevity.*@
Тег HTML <form>
использует следующие вспомогательные функции тегов:
- вспомогательная функция тега форм. При отправке формы строка фильтра отправляется на страницу Pages/Movies/Index в строке запроса.
- Вспомогательная функция тега Input
Сохраните изменения и проверьте работу фильтра.
Поиск по жанру
Обновите метод OnGetAsync
страницы Index, добавив следующий код:
public async Task OnGetAsync()
{
// Use LINQ to get list of genres.
IQueryable<string> genreQuery = from m in _context.Movie
orderby m.Genre
select m.Genre;
var movies = from m in _context.Movie
select m;
if (!string.IsNullOrEmpty(SearchString))
{
movies = movies.Where(s => s.Title.Contains(SearchString));
}
if (!string.IsNullOrEmpty(MovieGenre))
{
movies = movies.Where(x => x.Genre == MovieGenre);
}
Genres = new SelectList(await genreQuery.Distinct().ToListAsync());
Movie = await movies.ToListAsync();
}
Следующий код определяет запрос LINQ, который извлекает все жанры из базы данных.
// Use LINQ to get list of genres.
IQueryable<string> genreQuery = from m in _context.Movie
orderby m.Genre
select m.Genre;
Список жанров SelectList
создается путем проецирования отдельных жанров.
Genres = new SelectList(await genreQuery.Distinct().ToListAsync());
Добавление поиска по жанру на страницу Razor
Обновите элемент, как выделено в следующей
<form>
Index.cshtml
разметке:@page @model RazorPagesMovie.Pages.Movies.IndexModel @{ ViewData["Title"] = "Index"; } <h1>Index</h1> <p> <a asp-page="Create">Create New</a> </p> <form> <p> <select asp-for="MovieGenre" asp-items="Model.Genres"> <option value="">All</option> </select> <label>Title: <input type="text" asp-for="SearchString" /></label> <input type="submit" value="Filter" /> </p> </form> <table class="table"> @*Markup removed for brevity.*@
Проверьте работу приложения, выполнив поиск по жанру, по названию фильма и по обоим этим параметрам.
Следующие шаги
ASP.NET Core