日历归档 |
|
<< < 2024 - 11 > >> | Su | Mo | Tu | We | Th | Fr | Sa | | | | | | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 |
|
|
|
About Me |
|
|
ZhangSichu |
|
Male |
|
32 |
|
ZhangSichu@gmail.com |
|
ZhangSichu@hotmail.com |
|
ZhangSichu.com |
|
weibo.com/zhangsichu |
|
|
|
个人推荐 |
|
|
|
|
分类归档 |
|
|
|
|
My Friends |
|
|
|
|
[翻译] ASP.NET MVC 5 系列教程 [八] 搜索功能
|
原文地址: http://www.asp.net/mvc/overview/getting-started/introduction/adding-search
升级 Index页面 我们开始在方法现有MoviesController类中,更新Index方法。代码如下:
public ActionResult Index(string searchString) { var movies = from m in db.Movies select m; if (!String.IsNullOrEmpty(searchString)) { movies = movies.Where(s => s.Title.Contains(searchString)); } return View(movies); }
|
Index方法的第一行创建以下的LINQ查询,以选择看电影:
var movies = from m in db.Movies select m;
|
如果searchString参数包含一个字符串,可以使用下面的代码,修改电影查询要筛选的搜索字符串:
if (!String.IsNullOrEmpty(searchString)) { movies = movies.Where(s => s.Title.Contains(searchString)); }
|
上面s => s.Title 代码是一个Lambda 表达式。Lambda 是基于方法的LINQ查询,例如上面的where查询。在上面的代码中使用了标准查询参数运算符的方法。当定义LINQ查询或修改查询条件时,如调用Where 或OrderBy方法时,不会执行 LINQ 查询。相反,查询执行会被延迟,这意味着表达式的计算延迟,直到取得实际的值或调用ToList方法。在Search示例中,Index.cshtml视图中执行查询。有关延迟的查询执行的详细信息,请参阅Query Execution.
注:Contains 方法是运行在的数据库,而不是C#代码上面。在数据库中,Contains映射到to SQL LIKE,这是大小写不敏感的。
现在,您可以实现Index视图并将其显示给用户。
运行这个应用程序和导航到 /Movies/Index。追加一个查询字符串,URL如 ?searchString=ghost。筛选的影片会被显示。
如果你改变了Index方法签名参数名为id的,这个id参数将匹配{ id }的占位符。App_Start\ RouteConfig.cs文件中设置的缺省路由定义如下。
{controller}/{action}/{id}
|
原来的 Index 方法看起来如下所示:
public ActionResult Index(string searchString) { var movies = from m in db.Movies select m; if (!String.IsNullOrEmpty(searchString)) { movies = movies.Where(s => s.Title.Contains(searchString)); } return View(movies); }
|
修改后的 Index 方法看起来如下所示:
public ActionResult Index(string id) { string searchString = id; var movies = from m in db.Movies select m; if (!String.IsNullOrEmpty(searchString)) { movies = movies.Where(s => s.Title.Contains(searchString)); } return View(movies); }
|
现在,您可以通过路由数据(URL段)的标题搜索了,而不是作为查询字符串值,截图如下:
然而,你不能期望用户可以每次要搜索一部电影都会去修改URL。所以,现在你将添加用户界面,帮助他们来过滤影片。如果你改变Index方法来测试如何通过路由绑定ID参数的签名,Index方法需要一个字符串参数searchString:
public ActionResult Index(string searchString) { var movies = from m in db.Movies select m; if (!String.IsNullOrEmpty(searchString)) { movies = movies.Where(s => s.Title.Contains(searchString)); } return View(movies); }
|
打开文件 Views\Movies\Index.cshtml, 在这段代码@Html.ActionLink("Create New", "Create")后之后, 新增如下高亮的:
@model IEnumerable<MvcMovie.Models.Movie> @{ ViewBag.Title = "Index"; } <h2>Index</h2> <p> @Html.ActionLink("Create New", "Create") @using (Html.BeginForm()){ <p> Title: @Html.TextBox("SearchString") <br /> <input type="submit" value="Filter" /></p> } </p>
|
Html.BeginForm辅助会创建一个<form>标签。当用户通过点击“过滤器”按钮,提交表单, Html.BeginForm助手会导致窗体post到它本身。
Visual Studio2013中有一个很好的改善: 显示和编辑视图文件时。当你运行应用程序打开视图文件时,Visual Studio2013的将调用正确的控制器操作方法来展示视图。
在Visual Studio中打开使用Index视图(在上面的图片所示),点击Ctr F5或F5运行应用程序,然后试试搜索一部电影。
该Index 方法的HttpPost没有重载。 你不需要它,因为该方法不改变application的状态,只是过滤数据。
您可以添加以下httppost Index方法。在这种情况下,函数调用将匹配的HttpPost Index方法,的HttpPost Index方法运行的如下面的图片所示。
[HttpPost] public string Index(FormCollection fc, string searchString) { return "<h3> From [HttpPost]Index: " + searchString + "</h3>"; }
|
但是,即使您添加此HttpPost Index方法,这一实现其实是有局限的。想象一下您想要添加书签给特定的搜索,或者您想要把搜索链接发送给朋友们,他们可以通过单击看到一样的电影搜索列表。请注意 HTTP POST 请求的 URL 和GET 请求的URL 是相同的(localhost:xxxxx/电影/Index)— — 在 URL 中没有搜索信息。现在,搜索字符串信息作为窗体字段值,发送到服务器。这意味着您不能在 URL 中捕获此搜索信息,以添加书签或发送给朋友。
解决方法是使用重载的BeginForm,它指定 POST 请求应添加到 URL 的搜索信息,并应该路由到 HttpGet版的 Index方法。将现有的无参数BeginForm 方法,修改为以下内容
@using (Html.BeginForm("Index","Movies",FormMethod.Get))
|
现在当您提交搜索,该 URL 将包含搜索的查询字符串(query string)。搜索还会请求到 HttpGet Index操作方法,即使您也有一个HttpPost Index方法。
按照电影流派添加搜索 如果您添加了HttpPost 的Index方法,请立即删除它。 接下来,您将添加功能可以让用户按流派搜索电影。将Index方法替换成下面的代码:
public ActionResult Index(string movieGenre, string searchString) { var GenreLst = new List<string>();
var GenreQry = from d in db.Movies orderby d.Genre select d.Genre;
GenreLst.AddRange(GenreQry.Distinct()); ViewBag.movieGenre = new SelectList(GenreLst);
var movies = from m in db.Movies 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); }
return View(movies); }
|
这个版本的Index方法将接受一个附加的movieGenre参数。前几行的代码会创建一个List对象来保存数据库中的电影流派。
下面的代码是从数据库中检索所有流派的 LINQ 查询。
var GenreQry = from d in db.Movies orderby d.Genre select d.Genre;
|
该代码使用泛型 List集合的 AddRange方法将所有不同的流派,添加到集合中的。(使用 Distinct修饰符,不会添加重复的流派 -- 例如,在我们的示例中添加了两次喜剧)。
该代码然后在ViewBag对象中存储了流派的数据列表。的SelectList对象在ViewBag作为存储类数据(这样的电影流派),然后在下拉列表框中的数据访问类别,是一个典型的MVC applications的方法。
下面的代码演示如何检查movieGenre参数。如果它不是空的,代码进一步指定了所查询的电影流派。
if (!string.IsNullOrEmpty(movieGenre)) { movies = movies.Where(x => x.Genre == movieGenre); }
|
如前所述,查询数据不会在数据库上运行,直到电影列表迭代结束(恰发生在View,Index方法返回后)。
在Index视图添加标记,以支持按流派搜索电影 在Views\Movies\Index.cshtml 文件中,添加Html.DropDownList辅助方法,在TextBox前。完成的代码如下图所示:
@model IEnumerable<MvcMovie.Models.Movie> @{ ViewBag.Title = "Index"; } <h2>Index</h2> <p> @Html.ActionLink("Create New", "Create") @using (Html.BeginForm("Index", "Movies", FormMethod.Get)) { <p> Genre: @Html.DropDownList("movieGenre", "All") Title: @Html.TextBox("SearchString") <input type="submit" value="Filter" /> </p> } </p> <table class="table">
|
下面的代码:
@Html.DropDownList("movieGenre", "All")
|
ViewBag 中, "movieGenre" 参考作为key在DropDownList 中搜索IEnumerable<SelectListItem >. ViewBag填入的操作方法:
public ActionResult Index(string movieGenre, string searchString) { var GenreLst = new List<string>();
var GenreQry = from d in db.Movies orderby d.Genre select d.Genre;
GenreLst.AddRange(GenreQry.Distinct()); ViewBag.movieGenre = new SelectList(GenreLst);
var movies = from m in db.Movies 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); }
return View(movies); }
|
参数“All”提供的项列表中的预先选择的。如我们使用下面的代码:
@Html.DropDownList("movieGenre", "Comedy")
|
在我们的数据库中,我们拥有与“喜剧”流派的电影,“喜剧”在下拉列表中将预先选择。因为我们没有一个电影流派“All”,也没有“All”的SelectList,所以当我们post back后不做任何选择,movieGenre查询字符串值是空的。
运行应用程序并浏览/Movies/Index。尝试搜索流派,电影名称,并同时选择这两个条件。
在本节中,您创建了一个搜索的方法和视图,使用它,用户可以通过电影标题和流派来搜索。在下一节中,您将看到如何添加一个属性到Movie model,和如何添加一个初始值设定项值,它会自动创建一个测试数据库。
|
|
|
|
|
|