Часть 6. Добавление поиска в Razor Pages в ASP.NET Core

Примечание.

Это не последняя версия этой статьи. В текущем выпуске см . версию .NET 8 этой статьи.

Предупреждение

Эта версия ASP.NET Core больше не поддерживается. Дополнительные сведения см. в статье о политике поддержки .NET и .NET Core. В текущем выпуске см . версию .NET 8 этой статьи.

Внимание

Эта информация относится к предварительному выпуску продукта, который может быть существенно изменен до его коммерческого выпуска. Майкрософт не предоставляет никаких гарантий, явных или подразумеваемых, относительно приведенных здесь сведений.

В текущем выпуске см . версию .NET 8 этой статьи.

Автор: Рик Андерсон (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

Если на страницу Index добавлен следующий шаблон маршрута, строку поиска можно передать в виде сегмента URL-адреса. Например, https://localhost:5001/Movies/Ghost.

@page "{searchString?}"

Предыдущее ограничение маршрута разрешало поиск названия в виде данных маршрута (сегмент URL-адреса) вместо значения строки запроса. Символ ? в "{searchString?}" означает, что этот параметр является необязательным.

Представление Index, в URL-адрес которого добавлено слово ghost, возвращает два фильма: Ghostbusters и Ghostbusters 2

Среда выполнения 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> использует следующие вспомогательные функции тегов:

Сохраните изменения и проверьте работу фильтра.

Представление Index со словом ghost в текстовом поле фильтра по названию

Поиск по жанру

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

Если на страницу Index добавлен следующий шаблон маршрута, строку поиска можно передать в виде сегмента URL-адреса. Например, https://localhost:5001/Movies/Ghost.

@page "{searchString?}"

Предыдущее ограничение маршрута разрешало поиск названия в виде данных маршрута (сегмент URL-адреса) вместо значения строки запроса. Символ ? в "{searchString?}" означает, что этот параметр является необязательным.

Представление Index, в URL-адрес которого добавлено слово ghost, возвращает два фильма: Ghostbusters и Ghostbusters 2

Среда выполнения 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> использует следующие вспомогательные функции тегов:

Сохраните изменения и проверьте работу фильтра.

Представление Index со словом ghost в текстовом поле фильтра по названию

Поиск по жанру

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

Если на страницу Index добавлен следующий шаблон маршрута, строку поиска можно передать в виде сегмента URL-адреса. Например, https://localhost:5001/Movies/Ghost.

@page "{searchString?}"

Предыдущее ограничение маршрута разрешало поиск названия в виде данных маршрута (сегмент URL-адреса) вместо значения строки запроса. Символ ? в "{searchString?}" означает, что этот параметр является необязательным.

Представление Index, в URL-адрес которого добавлено слово ghost, возвращает два фильма: Ghostbusters и Ghostbusters 2

Среда выполнения 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> использует следующие вспомогательные функции тегов:

Сохраните изменения и проверьте работу фильтра.

Представление Index со словом ghost в текстовом поле фильтра по названию

Поиск по жанру

Обновите метод 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

Если на страницу Index добавлен следующий шаблон маршрута, строку поиска можно передать в виде сегмента URL-адреса. Например, https://localhost:5001/Movies/Ghost.

@page "{searchString?}"

Предыдущее ограничение маршрута разрешало поиск названия в виде данных маршрута (сегмент URL-адреса) вместо значения строки запроса. Символ ? в "{searchString?}" означает, что этот параметр является необязательным.

Представление Index, в URL-адрес которого добавлено слово ghost, возвращает два фильма: Ghostbusters и Ghostbusters 2

Среда выполнения 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> использует следующие вспомогательные функции тегов:

Сохраните изменения и проверьте работу фильтра.

Представление Index со словом ghost в текстовом поле фильтра по названию

Поиск по жанру

Обновите метод 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

Если на страницу Index добавлен следующий шаблон маршрута, строку поиска можно передать в виде сегмента URL-адреса. Например, https://localhost:5001/Movies/Ghost.

@page "{searchString?}"

Предыдущее ограничение маршрута разрешало поиск названия в виде данных маршрута (сегмент URL-адреса) вместо значения строки запроса. Символ ? в "{searchString?}" означает, что этот параметр является необязательным.

Представление Index, в URL-адрес которого добавлено слово ghost, возвращает два фильма: Ghostbusters и Ghostbusters 2

Среда выполнения 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> использует следующие вспомогательные функции тегов:

Сохраните изменения и проверьте работу фильтра.

Представление Index со словом ghost в текстовом поле фильтра по названию

Поиск по жанру

Обновите метод 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

  1. Обновите элемент, как выделено в следующей<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.*@
    
    
  2. Проверьте работу приложения, выполнив поиск по жанру, по названию фильма и по обоим этим параметрам.

Следующие шаги