原文: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. ADO.NET对象的详解

    1. Connection 类 和数据库交互,必须连接它.连接帮助指明数据库服务器.数据库名字.用户名.密码,和连接数据库所需要的其它参数.Connection对象会被Command对象使用,这样就能 ...

  2. UITextView 输入字数限制

    本文介绍了UITextView对中英文还有iOS自带表情输入的字数限制,由于中文输入会有联想导致字数限制不准确所以苦恼好久,所以参考一些大神的博客终于搞定,欢迎大家参考和指正. 对于限制UITextV ...

  3. Webstorm+Webpack+echarts构建个性化定制的数据可视化图表&&两个echarts详细教程(柱状图,南丁格尔图)

    Webstorm+Webpack+echarts   ECharts 特性介绍 ECharts,一个纯 Javascript 的图表库,可以流畅的运行在 PC 和移动设备上,兼容当前绝大部分浏览器(I ...

  4. CSS 选择器及各样式引用方式

    Css :层叠样式表 (Cascading Style Sheets),定义了如何显示HTML元素. 目录 1. 选择器的分类:介绍ID.class.元素名称.符合.层次.伪类.属性选择器. 2. 样 ...

  5. Spring之旅(2)

    Spring简化Java的下一个理念:基于切面的声明式编程 3.应用切面 依赖注入的目的是让相互协作的组件保持松散耦合:而AOP编程允许你把遍布应用各处的功能分离出来形成可重用的组件. AOP面向切面 ...

  6. JdbcTemplate+PageImpl实现多表分页查询

    一.基础实体 @MappedSuperclass public abstract class AbsIdEntity implements Serializable { private static ...

  7. Angular企业级开发(2)-搭建Angular开发环境

    1.集成开发环境 个人或团队开发AngularJS项目时,有很多JavaScript编辑器可以选择.使用优秀的集成开发环境(Integrated Development Environment)能节省 ...

  8. [C#] C# 知识回顾 - 你真的懂异常(Exception)吗?

    你真的懂异常(Exception)吗? 目录 异常介绍 异常的特点 怎样使用异常 处理异常的 try-catch-finally 捕获异常的 Catch 块 释放资源的 Finally 块 一.异常介 ...

  9. 我这么玩Web Api(二):数据验证,全局数据验证与单元测试

    目录 一.模型状态 - ModelState 二.数据注解 - Data Annotations 三.自定义数据注解 四.全局数据验证 五.单元测试   一.模型状态 - ModelState 我理解 ...

  10. 解决Android Studio 无法显示Layout视图问题

    在Android Studio 当中,如果你选择的SDK的版本 与你所显示的视图版本不一致时,会出现这个错误 Exception raised during rendering:com/android ...