第 6 部分,将搜索添加到 ASP.NET Core Razor 页面
注意
此版本不是本文的最新版本。 有关当前版本,请参阅本文的 .NET 9 版本。
警告
此版本的 ASP.NET Core 不再受支持。 有关详细信息,请参阅 .NET 和 .NET Core 支持策略。 对于当前版本,请参阅此文的 .NET 8 版本。
在以下部分中,添加了按流派或名称搜索电影。
将以下突出显示的代码添加到 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]
会绑定名称与属性相同的表单值和查询字符串。 在 HTTP GET 请求中进行绑定需要[BindProperty(SupportsGet = true)]
。Genres
:包含流派列表。Genres
使用户能够从列表中选择一种流派。SelectList
需要using Microsoft.AspNetCore.Mvc.Rendering;
MovieGenre
:包含用户选择的特定流派。 例如,“Western”。Genres
和MovieGenre
会在本教程的后续部分中使用。
警告
出于安全原因,必须选择绑定 GET
请求数据以对模型属性进行分页。 请在将用户输入映射到属性前对其进行验证。 当处理依赖查询字符串或路由值的方案时,选择加入 GET
绑定非常有用。
若要将属性绑定在 GET
请求上,请将 [BindProperty]
特性的 SupportsGet
属性设置为 true
:
[BindProperty(SupportsGet = true)]
有关详细信息,请参阅 ASP.NET Core Community Standup:GET 上的绑定讨论 (YouTube) 。
使用以下代码更新 Movies/Index
页面的 OnGetAsync
方法:
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()
代码是 Lambda 表达式。 Lambda 在基于方法的 LINQ 查询中用作标准查询运算符方法的参数,如 Where 方法或 Contains
。 在对 LINQ 查询进行定义或通过调用方法(如 Where
、Contains
或 OrderBy
)进行修改后,此查询不会执行。 相反,会延迟执行查询。 表达式的计算会延迟,直到循环访问其实现的值或者调用 ToListAsync
方法为止。 有关详细信息,请参阅 Query Execution(查询执行)。
注意
Contains 方法在数据库中运行,而不是在 C# 代码中运行。 查询是否区分大小写取决于数据库和排序规则。 在 SQL Server 上,Contains
映射到 SQL LIKE,这是不区分大小写的。 具有默认排序规则的 SQLite 是区分大小写和不区分大小写的组合,具体取决于查询。 有关进行不区分大小写的 SQLite 查询的信息,请参阅以下内容:
导航到电影页面,并向 URL 追加一个如 ?searchString=Ghost
的查询字符串。 例如 https://localhost:5001/Movies?searchString=Ghost
。 筛选的电影将显示出来。
如果向“索引”页面添加了以下路由模板,搜索字符串则可作为 URL 段传递。 例如 https://localhost:5001/Movies/Ghost
。
@page "{searchString?}"
前面的路由约束允许按路由数据(URL 段)搜索标题,而不是按查询字符串值进行搜索。 "{searchString?}"
中的 ?
表示这是可选路由参数。
ASP.NET Core 运行时使用模型绑定,通过查询字符串 (?searchString=Ghost
) 或路由数据 (https://localhost:5001/Movies/Ghost
) 设置 SearchString
属性的值。 模型绑定不区分大小写。
但是,用户不能通过修改 URL 来搜索电影。 在此步骤中,会添加 UI 来筛选电影。 如果已添加路由约束 "{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>
标记使用以下标记帮助程序:
保存更改并测试筛选器。
按流派搜索
使用以下代码更新 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 页面
更新 Index.cshtml
<form>
元素,如以下标记中突出显示的内容所示:
@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]
会绑定名称与属性相同的表单值和查询字符串。 在 HTTP GET 请求中进行绑定需要[BindProperty(SupportsGet = true)]
。Genres
:包含流派列表。Genres
使用户能够从列表中选择一种流派。SelectList
需要using Microsoft.AspNetCore.Mvc.Rendering;
MovieGenre
:包含用户选择的特定流派。 例如,“Western”。Genres
和MovieGenre
会在本教程的后续部分中使用。
警告
出于安全原因,必须选择绑定 GET
请求数据以对模型属性进行分页。 请在将用户输入映射到属性前对其进行验证。 当处理依赖查询字符串或路由值的方案时,选择加入 GET
绑定非常有用。
若要将属性绑定在 GET
请求上,请将 [BindProperty]
特性的 SupportsGet
属性设置为 true
:
[BindProperty(SupportsGet = true)]
有关详细信息,请参阅 ASP.NET Core Community Standup:GET 上的绑定讨论 (YouTube) 。
使用以下代码更新索引页面的 OnGetAsync
方法:
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()
代码是 Lambda 表达式。 Lambda 在基于方法的 LINQ 查询中用作标准查询运算符方法的参数,如 Where 方法或 Contains
。 在对 LINQ 查询进行定义或通过调用方法(如 Where
、Contains
或 OrderBy
)进行修改后,此查询不会执行。 相反,会延迟执行查询。 表达式的计算会延迟,直到循环访问其实现的值或者调用 ToListAsync
方法为止。 有关详细信息,请参阅 Query Execution(查询执行)。
注意
Contains 方法在数据库中运行,而不是在 C# 代码中运行。 查询是否区分大小写取决于数据库和排序规则。 在 SQL Server 上,Contains
映射到 SQL LIKE,这是不区分大小写的。 具有默认排序规则的 SQLite 是区分大小写和不区分大小写的组合,具体取决于查询。 有关进行不区分大小写的 SQLite 查询的信息,请参阅以下内容:
导航到电影页面,并向 URL 追加一个如 ?searchString=Ghost
的查询字符串。 例如 https://localhost:5001/Movies?searchString=Ghost
。 筛选的电影将显示出来。
如果向“索引”页面添加了以下路由模板,搜索字符串则可作为 URL 段传递。 例如 https://localhost:5001/Movies/Ghost
。
@page "{searchString?}"
前面的路由约束允许按路由数据(URL 段)搜索标题,而不是按查询字符串值进行搜索。 "{searchString?}"
中的 ?
表示这是可选路由参数。
ASP.NET Core 运行时使用模型绑定,通过查询字符串 (?searchString=Ghost
) 或路由数据 (https://localhost:5001/Movies/Ghost
) 设置 SearchString
属性的值。 模型绑定不区分大小写。
但是,用户不能通过修改 URL 来搜索电影。 在此步骤中,会添加 UI 来筛选电影。 如果已添加路由约束 "{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>
标记使用以下标记帮助程序:
保存更改并测试筛选器。
按流派搜索
使用以下代码更新 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 页面
更新 Index.cshtml
<form>
元素,如以下标记中突出显示的内容所示:
@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]
会绑定名称与属性相同的表单值和查询字符串。 在 HTTP GET 请求中进行绑定需要[BindProperty(SupportsGet = true)]
。Genres
:包含流派列表。Genres
使用户能够从列表中选择一种流派。SelectList
需要using Microsoft.AspNetCore.Mvc.Rendering;
MovieGenre
:包含用户选择的特定流派。 例如,“Western”。Genres
和MovieGenre
会在本教程的后续部分中使用。
警告
出于安全原因,必须选择绑定 GET
请求数据以对模型属性进行分页。 请在将用户输入映射到属性前对其进行验证。 当处理依赖查询字符串或路由值的方案时,选择加入 GET
绑定非常有用。
若要将属性绑定在 GET
请求上,请将 [BindProperty]
特性的 SupportsGet
属性设置为 true
:
[BindProperty(SupportsGet = true)]
有关详细信息,请参阅 ASP.NET Core Community Standup:GET 上的绑定讨论 (YouTube) 。
使用以下代码更新索引页面的 OnGetAsync
方法:
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()
代码是 Lambda 表达式。 Lambda 在基于方法的 LINQ 查询中用作标准查询运算符方法的参数,如 Where 方法或 Contains
。 在对 LINQ 查询进行定义或通过调用方法(如 Where
、Contains
或 OrderBy
)进行修改后,此查询不会执行。 相反,会延迟执行查询。 表达式的计算会延迟,直到循环访问其实现的值或者调用 ToListAsync
方法为止。 有关详细信息,请参阅 Query Execution(查询执行)。
注意
Contains 方法在数据库中运行,而不是在 C# 代码中运行。 查询是否区分大小写取决于数据库和排序规则。 在 SQL Server 上,Contains
映射到 SQL LIKE,这是不区分大小写的。 具有默认排序规则的 SQLite 是区分大小写和不区分大小写的组合,具体取决于查询。 有关进行不区分大小写的 SQLite 查询的信息,请参阅以下内容:
导航到电影页面,并向 URL 追加一个如 ?searchString=Ghost
的查询字符串。 例如 https://localhost:5001/Movies?searchString=Ghost
。 筛选的电影将显示出来。
如果向“索引”页面添加了以下路由模板,搜索字符串则可作为 URL 段传递。 例如 https://localhost:5001/Movies/Ghost
。
@page "{searchString?}"
前面的路由约束允许按路由数据(URL 段)搜索标题,而不是按查询字符串值进行搜索。 "{searchString?}"
中的 ?
表示这是可选路由参数。
ASP.NET Core 运行时使用模型绑定,通过查询字符串 (?searchString=Ghost
) 或路由数据 (https://localhost:5001/Movies/Ghost
) 设置 SearchString
属性的值。 模型绑定不区分大小写。
但是,用户不能通过修改 URL 来搜索电影。 在此步骤中,会添加 UI 来筛选电影。 如果已添加路由约束 "{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>
标记使用以下标记帮助程序:
保存更改并测试筛选器。
按流派搜索
使用以下代码更新索引页面的 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 页面
更新 Index.cshtml
<form>
元素,如以下标记中突出显示的内容所示:
@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]
会绑定名称与属性相同的表单值和查询字符串。 在 HTTP GET 请求中进行绑定需要[BindProperty(SupportsGet = true)]
。Genres
:包含流派列表。Genres
使用户能够从列表中选择一种流派。SelectList
需要using Microsoft.AspNetCore.Mvc.Rendering;
MovieGenre
:包含用户选择的特定流派。 例如,“Western”。Genres
和MovieGenre
会在本教程的后续部分中使用。
警告
出于安全原因,必须选择绑定 GET
请求数据以对模型属性进行分页。 请在将用户输入映射到属性前对其进行验证。 当处理依赖查询字符串或路由值的方案时,选择加入 GET
绑定非常有用。
若要将属性绑定在 GET
请求上,请将 [BindProperty]
特性的 SupportsGet
属性设置为 true
:
[BindProperty(SupportsGet = true)]
有关详细信息,请参阅 ASP.NET Core Community Standup:GET 上的绑定讨论 (YouTube) 。
使用以下代码更新索引页面的 OnGetAsync
方法:
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()
代码是 Lambda 表达式。 Lambda 在基于方法的 LINQ 查询中用作标准查询运算符方法的参数,如 Where 方法或 Contains
。 在对 LINQ 查询进行定义或通过调用方法(如 Where
、Contains
或 OrderBy
)进行修改后,此查询不会执行。 相反,会延迟执行查询。 表达式的计算会延迟,直到循环访问其实现的值或者调用 ToListAsync
方法为止。 有关详细信息,请参阅 Query Execution(查询执行)。
注意
Contains 方法在数据库中运行,而不是在 C# 代码中运行。 查询是否区分大小写取决于数据库和排序规则。 在 SQL Server 上,Contains
映射到 SQL LIKE,这是不区分大小写的。 具有默认排序规则的 SQLite 是区分大小写和不区分大小写的组合,具体取决于查询。 有关进行不区分大小写的 SQLite 查询的信息,请参阅以下内容:
导航到电影页面,并向 URL 追加一个如 ?searchString=Ghost
的查询字符串。 例如 https://localhost:5001/Movies?searchString=Ghost
。 筛选的电影将显示出来。
如果向“索引”页面添加了以下路由模板,搜索字符串则可作为 URL 段传递。 例如 https://localhost:5001/Movies/Ghost
。
@page "{searchString?}"
前面的路由约束允许按路由数据(URL 段)搜索标题,而不是按查询字符串值进行搜索。 "{searchString?}"
中的 ?
表示这是可选路由参数。
ASP.NET Core 运行时使用模型绑定,通过查询字符串 (?searchString=Ghost
) 或路由数据 (https://localhost:5001/Movies/Ghost
) 设置 SearchString
属性的值。 模型绑定不区分大小写。
但是,用户不能通过修改 URL 来搜索电影。 在此步骤中,会添加 UI 来筛选电影。 如果已添加路由约束 "{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>
标记使用以下标记帮助程序:
保存更改并测试筛选器。
按流派搜索
使用以下代码更新索引页面的 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 页面
更新 Index.cshtml
<form>
元素,如以下标记中突出显示的内容所示:
@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]
会绑定名称与属性相同的表单值和查询字符串。 在 HTTP GET 请求中进行绑定需要[BindProperty(SupportsGet = true)]
。Genres
:包含流派列表。Genres
使用户能够从列表中选择一种流派。SelectList
需要using Microsoft.AspNetCore.Mvc.Rendering;
MovieGenre
:包含用户选择的特定流派。 例如,“Western”。Genres
和MovieGenre
会在本教程的后续部分中使用。
警告
出于安全原因,必须选择绑定 GET
请求数据以对模型属性进行分页。 请在将用户输入映射到属性前对其进行验证。 当处理依赖查询字符串或路由值的方案时,选择加入 GET
绑定非常有用。
若要将属性绑定在 GET
请求上,请将 [BindProperty]
特性的 SupportsGet
属性设置为 true
:
[BindProperty(SupportsGet = true)]
有关详细信息,请参阅 ASP.NET Core Community Standup:GET 上的绑定讨论 (YouTube) 。
使用以下代码更新索引页面的 OnGetAsync
方法:
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()
代码是 Lambda 表达式。 Lambda 在基于方法的 LINQ 查询中用作标准查询运算符方法的参数,如 Where 方法或 Contains
。 在对 LINQ 查询进行定义或通过调用方法(如 Where
、Contains
或 OrderBy
)进行修改后,此查询不会执行。 相反,会延迟执行查询。 表达式的计算会延迟,直到循环访问其实现的值或者调用 ToListAsync
方法为止。 有关详细信息,请参阅 Query Execution(查询执行)。
注意
Contains 方法在数据库中运行,而不是在 C# 代码中运行。 查询是否区分大小写取决于数据库和排序规则。 在 SQL Server 上,Contains
映射到 SQL LIKE,这是不区分大小写的。 具有默认排序规则的 SQLite 是区分大小写和不区分大小写的组合,具体取决于查询。 有关进行不区分大小写的 SQLite 查询的信息,请参阅以下内容:
导航到电影页面,并向 URL 追加一个如 ?searchString=Ghost
的查询字符串。 例如 https://localhost:5001/Movies?searchString=Ghost
。 筛选的电影将显示出来。
如果向“索引”页面添加了以下路由模板,搜索字符串则可作为 URL 段传递。 例如 https://localhost:5001/Movies/Ghost
。
@page "{searchString?}"
前面的路由约束允许按路由数据(URL 段)搜索标题,而不是按查询字符串值进行搜索。 "{searchString?}"
中的 ?
表示这是可选路由参数。
ASP.NET Core 运行时使用模型绑定,通过查询字符串 (?searchString=Ghost
) 或路由数据 (https://localhost:5001/Movies/Ghost
) 设置 SearchString
属性的值。 模型绑定不区分大小写。
但是,用户不能通过修改 URL 来搜索电影。 在此步骤中,会添加 UI 来筛选电影。 如果已添加路由约束 "{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>
标记使用以下标记帮助程序:
保存更改并测试筛选器。
按流派搜索
使用以下代码更新索引页面的 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 页面
更新
Index.cshtml
<form>
元素,如以下标记中突出显示的内容所示:@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.*@
通过按流派或/和电影标题搜索来测试应用。