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 方法运行结果如下所示。