原文:Adding Search

作者:Rick Anderson

翻译:魏美娟(初见)

校对:谢炀(Kiler) 、孟帅洋(书缘)张仁建(第二年.夏)

在本节中,你可以为 Index 方法添加查询功能,使其能够根据电影的 genrename 进行查找。

更新 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 语句在定义或调用类似 WhereContains 或者 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)添加搜索的更多相关文章

  1. ASP.NET Core 中文文档 第二章 指南(4.6)Controller 方法与视图

    原文:Controller methods and views 作者:Rick Anderson 翻译:谢炀(Kiler) 校对:孟帅洋(书缘) .张仁建(第二年.夏) .许登洋(Seay) .姚阿勇 ...

  2. ASP.NET Core 中文文档 第二章 指南(4.4)添加 Model

    原文:Adding a model 作者:Rick Anderson 翻译:娄宇(Lyrics) 校对:许登洋(Seay).孟帅洋(书缘).姚阿勇(Mr.Yao).夏申斌 在这一节里,你将添加一些类来 ...

  3. ASP.NET Core 中文文档 第二章 指南 (09) 使用 Swagger 生成 ASP.NET Web API 在线帮助测试文档

    原文:ASP.NET Web API Help Pages using Swagger 作者:Shayne Boyer 翻译:谢炀(kiler) 翻译:许登洋(Seay) 对于开发人员来说,构建一个消 ...

  4. 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 ...

  5. 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 ...

  6. ASP.NET Core 中文文档 第二章 指南(3)用 Visual Studio 发布一个 Azure 云 Web 应用程序

    原文:Getting Started 作者:Rick Anderson 翻译:谢炀(Kiler) 校对:孟帅洋(书缘).刘怡(AlexLEWIS).何镇汐 设置开发环境 安装最新版本的 Azure S ...

  7. 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 ...

  8. ASP.NET Core 中文文档 第二章 指南(4.5)使用 SQL Server LocalDB

    原文:Working with SQL Server LocalDB 作者:Rick Anderson 翻译: 魏美娟(初见) 校对: 孟帅洋(书缘).张硕(Apple).许登洋(Seay) Appl ...

  9. ASP.NET Core 中文文档 第二章 指南(5) 在 Nano Server 上运行ASP.NET Core

    原文 ASP.NET Core on Nano Server 作者 Sourabh Shirhatti 翻译 娄宇(Lyrics) 校对 刘怡(AlexLEWIS).许登洋(Seay).谢炀(kile ...

  10. ASP.NET Core 中文文档 第二章 指南(8) 使用 dotnet watch 开发 ASP.NET Core 应用程序

    原文:Developing ASP.NET Core applications using dotnet watch 作者:Victor Hurdugaci 翻译:谢炀(Kiler) 校对:刘怡(Al ...

随机推荐

  1. 数据库优化案例——————某市中心医院HIS系统

    记得在自己学习数据库知识的时候特别喜欢看案例,因为优化的手段是容易掌握的,但是整体的优化思想是很难学会的.这也是为什么自己特别喜欢看案例,今天也开始分享自己做的优化案例. 最近一直很忙,博客产出也少的 ...

  2. iOS热更新-8种实现方式

    一.JSPatch 热更新时,从服务器拉去js脚本.理论上可以修改和新建所有的模块,但是不建议这样做. 建议 用来做紧急的小需求和 修复严重的线上bug. 二.lua脚本 比如: wax.热更新时,从 ...

  3. HTML中上传与读取图片或文件(input file)----在路上(25)

    input file相关知识简例 在此介绍的input file相关知识为: 上传照片及文件,其中包括单次上传.批量上传.删除照片.增加照片.读取图片.对上传的图片或文件的判断,比如限制图片的张数.限 ...

  4. AFNetworking 3.0 源码解读(十一)之 UIButton/UIProgressView/UIWebView + AFNetworking

    AFNetworking的源码解读马上就结束了,这一篇应该算是倒数第二篇,下一篇会是对AFNetworking中的技术点进行总结. 前言 上一篇我们总结了 UIActivityIndicatorVie ...

  5. Html.DropDownLis绑定数据库

    效果: 方法一: View: <div class="col-md-md-4"> <div class="input-group"> & ...

  6. 基于Ubuntu Hadoop的群集搭建Hive

    Hive是Hadoop生态中的一个重要组成部分,主要用于数据仓库.前面的文章中我们已经搭建好了Hadoop的群集,下面我们在这个群集上再搭建Hive的群集. 1.安装MySQL 1.1安装MySQL ...

  7. 解决WINDOWS防火墙开启后Ping不通

    WINDOWS系统由于安全考虑,当开启防火墙时,默认不允许外主机对其进行ping功能,即别的电脑ping不通本机.别的主机ping不通本机是因为本机的防火墙关闭了ICMP回显功能,只要把这回显功能打开 ...

  8. Windows Server 2008 R2常规安全设置及基本安全策略

    这篇文章主要介绍了Windows Web Server 2008 R2服务器简单安全设置,需要的朋友可以参考下 用的腾讯云最早选购的时候悲催的只有Windows Server 2008 R2的系统,原 ...

  9. EChart系列:在echart3中使用百度地图扩展之后,如何获取到百度地图对象

    最近做项目想要在百度地图上叠加显示echart的散点图,然后根据地图的缩放等级和区域范围要显示不同的散点图,这中间折腾了好久.功能要求包括: (1)底图使用百度地图: (2)可以在地图上叠加显示ech ...

  10. 聊聊从web session的共享到可扩展缓存设计

    先从web session的共享说起   许多系统需要提供7*24小时服务,这类系统肯定需要考虑灾备问题,单台服务器如果宕机可能无法立马恢复使用,这必定影响到服务.这个问题对于系统规模来说,从小到大可 ...