ASP.NET Core 中文文档 第二章 指南(4.7)添加搜索
原文:Adding Search
作者:Rick Anderson
翻译:魏美娟(初见)
校对:谢炀(Kiler) 、孟帅洋(书缘)、张仁建(第二年.夏)
在本节中,你可以为 Index 方法添加查询功能,使其能够根据电影的 genre 或 name 进行查找。
更新 Index 方法来开启搜索功能:
public async Task<IActionResult> Index(string searchString)
{
var movies = from m in _context.Movie
select m;
if (!String.IsNullOrEmpty(searchString))
{
movies = movies.Where(s => s.Title.Contains(searchString));
}
return View(await movies.ToListAsync());
}
Index 方法的第一行代码创建了一个LINQ查询,用来查找符合条件的电影:
var movies = from m in _context.Movie
select m;
这个查询 仅仅只是 在这里被定义出来,但是 并未 在数据库中执行。
如果 searchString 参数包含一个字符串,movies 查询将会添加对应查询过滤条件( 译者注 本例为 Title 包含 searchString 查询条件),代码如下:
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 方法才具备真正的值。更多关于延时查询的信息。请参考 查询执行 。
注意
Contains方法是在数据库中运行的,并非在上面的 C# 代码中。在数据库中,Contains方法被翻译为不区分大小写的SQL LIKE脚本。
运行应用程序,并导航到 /Movies/Index,在 URL 后面添加一个查询字符串,例如 ?searchString=ghost,被过滤后的电影列表如下:

如果你修改 Index 方法签名使得方法包含一个名为 id 的参数,那么 id 参数将会匹配 Startup.cs 文件中的默认路由中的可选项 {id} 。
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}"); //手工高亮
});
你可以使用 rename 操作快速的把 searchString 参数重命名为 id,在 searchString 上右击 > Rename 。

会被重命名的代码会高亮显示。

修改参数为 id ,其他引用到 searchString 的地方也会自动变更为 id。

修改前的 Index 方法:
public async Task<IActionResult> Index(string searchString) //手工高亮
{
var movies = from m in _context.Movie
select m;
if (!String.IsNullOrEmpty(searchString)) //手工高亮
{
movies = movies.Where(s => s.Title.Contains(searchString)); //手工高亮
}
return View(await movies.ToListAsync());
}
修改后的 Index 方法:
public async Task<IActionResult> Index(string id) //手工高亮
{
var movies = from m in _context.Movie
select m;
if (!String.IsNullOrEmpty(id)) //手工高亮
{
movies = movies.Where(s => s.Title.Contains(id)); //手工高亮
}
return View(await movies.ToListAsync());
}
修改完成以后,我们可以通过路由数据(URL 区块)来传递标题搜索条件而非查询字符串:

然而,你不能指望用户每次都通过修改URL来查找电影,因此你需要在界面上帮助他们过滤数据。如果你想要修改 Index 方法的签名并测试了路由绑定是如何传递 ID 参数,现在再把它改成原来的参数 searchString 。
public async Task<IActionResult> Index(string searchString) //手工高亮
{
var movies = from m in _context.Movie
select m;
if (!String.IsNullOrEmpty(searchString)) //手工高亮
{
movies = movies.Where(s => s.Title.Contains(searchString)); //手工高亮
}
return View(await movies.ToListAsync());
}
@model IEnumerable<MvcMovie.Models.Movie>
@{
ViewData["Title"] = "Index";
}
<h2>Index</h2>
<p>
<a asp-action="Create">Create New</a>
</p>
<!--下面的整个form标签高亮-->
<form asp-controller="Movies" asp-action="Index">
<p>
Title: <input type="text" name="SearchString">
<input type="submit" value="Filter" />
</p>
</form>
<table class="table">
<thead>
HTML <form> 标签使用Form Tag Helper生成,所以当你提交表单的时候,过滤字符串都被传到了 movies 控制器的 Index 方法。保存你的修改并测试过滤。

然而 Index 方法并没有你所希望的 [HttpPost] 重载。你也不需要,因为方法并不会修改应用程序的状态,仅仅只是过滤数据。
你可以添加下面的 [HttpPost] Index 方法。
[HttpPost] //手工高亮
public string Index(string searchString, bool notUsed)
{
return "From [HttpPost]Index: filter on " + searchString;
}
notUsed 参数用创建 Index 方法重载。我们在后续教程中会讨论。
如果你添加了这个方法。action 会调用匹配 [HttpPost] Index 的方法, [HttpPost] Index 方法运行结果如下所示。

然而,尽管添加了 [HttpPost] 版的 Index 方法,在实现的时候仍然存在一些局限性。设想你想将一个比较详细的查询添加书签,或者你想将查询结果以链接形式发送给朋友以便于你的朋友可以看到同样的过滤结果的电影,注意观察 HTTP POST 请求的时候,URL 是没有改变的(仍然是 localhost:xxxxx/Movies/Index),这个地址本身不包含查询信息。现在,查询信息是作为表单数据发送到服务器的,你可以通过 F12 开发者工具或者优秀的抓包工具 Fiddler tool。启动F12 开发者工具。
选择 http://localhost:xxx/Movies HTTP POST 200 行点击 Body > Request Body。

你可以在请求正文中看到查询参数和上一个教程中提到的XSRF令牌。Form Tag Helper生成XSRF 反伪造令牌。我们没有修改数据,所以无需在控制器方法中验证令牌。
因为查询参数在请求正文中而不是 Url 里,所以你在书签里面无法保存查询参数并共享给他人,为了解决这个问题,我们必须把请求指定为 HTTP GET。注意智能感知将帮我们更新标签。


请注意, <form> 标签中的专有标记。这种专有标记表示的标签是由Tag Helpers 支持的。

当你提交检索的时候,URL 包含查询条件,如果存在 HttpPost Index 方法,查询会跳转到 HttpGet Index 方法。

添加按照 Genre 查询
在 Models 目录添加下面的 MovieGenreViewModel 类:
using Microsoft.AspNetCore.Mvc.Rendering;
using System.Collections.Generic;
namespace MvcMovie.Models
{
public class MovieGenreViewModel
{
public List<Movie> movies;
public SelectList genres;
public string movieGenre { get; set; }
}
}
move-genre 视图模型包含:
- 电影列表
- 包含 genre 列表的SelectList。允许用户从列表中选择 genre 。
movieGenre,包含选中的 genre
用下面的代码替换 Index 方法:
public async Task<IActionResult> Index(string movieGenre, string searchString)
{
IQueryable<string> genreQuery = from m in _context.Movie
orderby m.Genre
select m.Genre;
var movies = from m in _context.Movie
select m;
if (!String.IsNullOrEmpty(searchString))
{
movies = movies.Where(s => s.Title.Contains(searchString));
}
if (!String.IsNullOrEmpty(movieGenre))
{
movies = movies.Where(x => x.Genre == movieGenre);
}
var movieGenreVM = new MovieGenreViewModel();
movieGenreVM.genres = new SelectList(await genreQuery.Distinct().ToListAsync());
movieGenreVM.movies = await movies.ToListAsync();
return View(movieGenreVM);
}
下面代码是通过 LINQ 语句从数据库中检索所有 genre 数据。
IQueryable<string> genreQuery = from m in _context.Movie
orderby m.Genre
select m.Genre;
SelectList 的 genres 通过 Distinct 方法投影查询创建(我们不想选择列表中出现重复的数据)。
movieGenreVM.genres = new SelectList(await genreQuery.Distinct().ToListAsync());
在 Index 视图中添加通过 genre 检索
<!--手工高亮-->
@model MovieGenreViewModel
@{
ViewData["Title"] = "Index";
}
<h2>Index</h2>
<p>
<a asp-action="Create">Create New</a>
</p>
<form asp-controller="Movies" asp-action="Index" method="get">
<p>
<select asp-for="movieGenre" asp-items="Model.genres"> <!--手工高亮-->
<option value="">All</option> <!--手工高亮-->
</select> <!--手工高亮-->
Title: <input type="text" name="SearchString">
<input type="submit" value="Filter" />
</p>
</form>
<table class="table">
<tr>
<th>
@Html.DisplayNameFor( model => model.movies[0].Genre ) <!--手工高亮-->
</th>
<th>
@Html.DisplayNameFor( model => model.movies[0].Price )
</th>
<th>
@Html.DisplayNameFor( model => model.movies[0].ReleaseDate )
</th>
<th>
@Html.DisplayNameFor( model => model.movies[0].Title )
</th>
<th></th>
</tr>
<tbody>
@foreach( var item in Model.movies ) //手工高亮
{
<tr>
<td>
@Html.DisplayFor( modelItem => item.Genre )
</td>
<td>
@Html.DisplayFor( modelItem => item.Price )
</td>
<td>
@Html.DisplayFor( modelItem => item.ReleaseDate )
</td>
<td>
@Html.DisplayFor( modelItem => item.Title )
</td>
<td>
<a asp-action="Edit" asp-route-id="@item.ID">Edit</a> |
<a asp-action="Details" asp-route-id="@item.ID">Details</a> |
<a asp-action="Delete" asp-route-id="@item.ID">Delete</a>
</td>
</tr>
}
</tbody>
</table>
测试程序并分别通过 genre 或者 电影标题以及两个条件同时进行检索
ASP.NET Core 中文文档 第二章 指南(4.7)添加搜索的更多相关文章
- ASP.NET Core 中文文档 第二章 指南(4.6)Controller 方法与视图
原文:Controller methods and views 作者:Rick Anderson 翻译:谢炀(Kiler) 校对:孟帅洋(书缘) .张仁建(第二年.夏) .许登洋(Seay) .姚阿勇 ...
- ASP.NET Core 中文文档 第二章 指南(4.4)添加 Model
原文:Adding a model 作者:Rick Anderson 翻译:娄宇(Lyrics) 校对:许登洋(Seay).孟帅洋(书缘).姚阿勇(Mr.Yao).夏申斌 在这一节里,你将添加一些类来 ...
- ASP.NET Core 中文文档 第二章 指南 (09) 使用 Swagger 生成 ASP.NET Web API 在线帮助测试文档
原文:ASP.NET Web API Help Pages using Swagger 作者:Shayne Boyer 翻译:谢炀(kiler) 翻译:许登洋(Seay) 对于开发人员来说,构建一个消 ...
- ASP.NET Core 中文文档 第二章 指南(1)用 Visual Studio Code 在 macOS 上创建首个 ASP.NET Core 应用程序
原文:Your First ASP.NET Core Application on a Mac Using Visual Studio Code 作者:Daniel Roth.Steve Smith ...
- ASP.NET Core 中文文档 第二章 指南(2)用 Visual Studio 和 ASP.NET Core MVC 创建首个 Web API
原文:Building Your First Web API with ASP.NET Core MVC and Visual Studio 作者:Mike Wasson 和 Rick Anderso ...
- ASP.NET Core 中文文档 第二章 指南(3)用 Visual Studio 发布一个 Azure 云 Web 应用程序
原文:Getting Started 作者:Rick Anderson 翻译:谢炀(Kiler) 校对:孟帅洋(书缘).刘怡(AlexLEWIS).何镇汐 设置开发环境 安装最新版本的 Azure S ...
- ASP.NET Core 中文文档 第二章 指南(4.1)ASP.NET Core MVC 与 Visual Studio 入门
原文:Getting started with ASP.NET Core MVC and Visual Studio 作者:Rick Anderson 翻译:娄宇(Lyrics) 校对:刘怡(Alex ...
- ASP.NET Core 中文文档 第二章 指南(4.5)使用 SQL Server LocalDB
原文:Working with SQL Server LocalDB 作者:Rick Anderson 翻译: 魏美娟(初见) 校对: 孟帅洋(书缘).张硕(Apple).许登洋(Seay) Appl ...
- ASP.NET Core 中文文档 第二章 指南(5) 在 Nano Server 上运行ASP.NET Core
原文 ASP.NET Core on Nano Server 作者 Sourabh Shirhatti 翻译 娄宇(Lyrics) 校对 刘怡(AlexLEWIS).许登洋(Seay).谢炀(kile ...
- ASP.NET Core 中文文档 第二章 指南(8) 使用 dotnet watch 开发 ASP.NET Core 应用程序
原文:Developing ASP.NET Core applications using dotnet watch 作者:Victor Hurdugaci 翻译:谢炀(Kiler) 校对:刘怡(Al ...
随机推荐
- Gradle配置APK自动签名完整流程
转载请注明出处:http://www.cnblogs.com/LT5505/p/6256683.html 一.生成签名 1.命令行生成签名,输入命令keytool -genkey -v -keysto ...
- ASP.NET MVC5+EF6+EasyUI 后台管理系统(74)-微信公众平台开发-自定义菜单
系列目录 引言 1.如果不借用Senparc.Weixin SDK自定义菜单,编码起来,工作量是非常之大 2.但是借助SDK似乎一切都是简单得不要不要的 3.自定义菜单无需要建立数据库表 4.自定义菜 ...
- submit text3常用快捷键
在网上找了一些submit text的快捷键: Ctrl+D 选词 (反复按快捷键,即可继续向下同时选中下一个相同的文本进行同时编辑)Ctrl+G 跳转到相应的行Ctrl+J 合并行(已选择需要合并的 ...
- 自定义搭建PHP开发环境
学习了一段时间php了,因为之前是刚接触php,所以用的是集成安装包(wamp).现在想进一步了解apache.mysql.php之间的关系以及提升自己所以进行自定义搭建PHP开发环境.废话不多说,请 ...
- JS继承之寄生类继承
原型式继承 其原理就是借助原型,可以基于已有的对象创建新对象.节省了创建自定义类型这一步(虽然觉得这样没什么意义). 模型 function object(o){ function W(){ } W. ...
- git-2.10.2-64-bit介绍&&git下载&&git安装教程
Git介绍 分布式:Git系统是一个分布式的系统,是用来保存工程源代码历史状态的命令行工具. 保存点:Git的保存点可以追踪源码中的文件, 并能得到某一个时间点上的整个工程项目的状态:可以在该保存点将 ...
- Java消息队列--JMS概述
1.什么是JMS JMS即Java消息服务(Java Message Service)应用程序接口,是一个Java平台中关于面向消息中间件(MOM)的API,用于在两个应用程序之间,或分布式系统中发送 ...
- win10电脑优化
Windows10必做的优化 --道心 关闭服务 右键点击"此电脑",选择"管理",进入"计算机管理"窗口. 在左侧的菜单选择"服 ...
- Princeton Algorithms week3 Assignment
这周编程作业是实现检测点共线的算法.和排序算法有关系的地方在于,对斜率排序后可以很快的检测出来哪些点是共线的,另外这个算法的瓶颈也在于排序的性能. 一点收获: java传参数时传递的是值,这很多人都知 ...
- mysql集群(双主)
0.安装 所谓双主基本可以理解为两台服务器互为主备,其核心思路与主备配置相同. 服务器A: 内网IP: 10.44.94.219 服务器B: 内网IP: 10.44.94.97 1.配置服务器A lo ...