原文:https://docs.microsoft.com/zh-cn/aspnet/mvc/overview/getting-started/introduction/adding-search
一、添加搜索方法和搜索视图
在本部分中,你将添加到搜索功能Index
操作方法,您可以搜索电影的流派或名称。
二、系统必备
若要匹配此部分的屏幕截图,需要运行应用程序 (F5),并将以下电影添加到数据库。
标题 | 发布日期 | 流派 | 价格 |
---|---|---|---|
Ghostbusters | 6/8/1984 | 喜剧 | 6.99 |
Ghostbusters II | 6/16/1989 | 喜剧 | 6.99 |
颗行星的大猩猩 | 3/27/1986 | 操作 | 5.99 |
三、更新索引窗体
通过更新开始Index
到现有的操作方法MoviesController
类。 下面是代码:
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查询用作标准查询运算符方法的参数,如其中上述代码中使用的方法。 进行定义或通过调用一个方法,如修改后不会执行 LINQ 查询Where
或OrderBy
。 相反,延迟查询执行,这意味着表达式的计算延迟,直到真正循环访问其实现的值或 ToList
调用方法。 在中Search
示例中,该查询中执行Index.cshtml视图。 有关延迟执行查询的详细信息,请参阅Query Execution(查询执行)。
现在可以更新Index
将向用户显示窗体的视图。
运行应用程序并导航到 /Movies/Index。 将查询字符串(如 ?searchString=ghost
)追加到 URL。 筛选的电影将显示出来。
如果您更改的签名Index
方法,以使名为的参数id
,则id
参数将匹配{id}
占位符默认路由中的设置应用_用户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。 因此需要添加 UI 来帮助他们筛选电影。 如果已更改的签名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);
}
打开ViewsMoviesIndex.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
帮助器后,窗体会发布到其自身,当用户通过单击提交窗体筛选器按钮。
Visual Studio 2013 具有较好的改进时显示和编辑视图文件。 当你运行应用程序时的视图文件打开时,Visual Studio 2013 调用正确的控制器操作方法,以显示该视图。
索引视图 (如在上图中所示) 在 Visual Studio 中打开,点击 Ctr F5 或按 F5 运行应用程序,然后再尝试搜索电影。
没有任何HttpPost
重载Index
方法。 您不需要它,因为该方法不更改状态的应用程序,只需筛选数据。
可添加以下 HttpPost Index
方法。 在这种情况下,操作调用程序将匹配HttpPost Index
方法,和HttpPost Index
方法将运行下图中所示。
[HttpPost]
public string Index(FormCollection fc, string searchString)
{
return "<h3> From [HttpPost]Index: " + searchString + "</h3>";
}
但是,即使添加 Index
方法的 HttpPost
版本,其实现方式也受到限制。 假设你想要将特定搜索加入书签,或向朋友发送一个链接,让他们单击链接即可查看筛选出的相同电影列表。 请注意,HTTP POST 请求的 URL 是 GET 请求 (localhost:xxxxx/Movies/Index) 的 URL 相同--没有 URL 本身中的搜索信息。 右现在,搜索字符串信息发送到服务器作为窗体字段值。 这意味着无法捕获该搜索信息加入书签或发送给朋友,在 URL 中。
解决方法是使用的重载BeginForm
,它指定 POST 请求,应将搜索信息添加到 URL,并且应路由到HttpGet
版本的Index
方法。 替换现有无参数BeginForm
方法替换为以下标记:
@using (Html.BeginForm("Index","Movies",FormMethod.Get))
现在提交搜索时,URL 包含搜索查询字符串。 即使具备 HttpPost Index
方法,搜索也将转到 HttpGet 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;
该代码使用AddRange
方法的泛型List
集合以添加到列表中的所有不同的流派。 (而无需Distinct
修饰符,则添加重复的流派 — 例如,将在我们的示例中两次添加喜剧)。 然后代码将存储在流派列表的ViewBag.MovieGenre
对象。 将类别数据 (此类电影流派) 作为SelectList对象中ViewBag
,则访问下拉列表框中的类别数据是典型的 MVC 应用程序的方法。
下面的代码演示了如何检查movieGenre
参数。 如果不为空,则代码进一步约束电影查询,以限制到指定类型的所选的电影。
if (!string.IsNullOrEmpty(movieGenre))
{
movies = movies.Where(x => x.Genre == movieGenre);
}
如前面所述,运行查询时不在数据库上直到电影列表循环访问 (这在视图中,会发生后Index
操作方法返回)。
五、将标记添加到索引视图,以支持按流派搜索
添加Html.DropDownList
到帮助程序ViewsMoviesIndex.cshtml文件,再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")
参数"MovieGenre"提供的键DropDownList
帮助器以查找IEnumerable<SelectListItem>
中ViewBag
。 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"提供选项标签参数。 如果在浏览器中查看该选择,您将看到其"值"属性为空。 由于我们的控制器仅筛选if
字符串不是null
或为空,将提交为空值movieGenre
显示所有流派。
此外可以设置默认情况下选择的选项。 如果您希望"喜剧"作为默认选项,则会更改控制器中的代码如下所示:
ViewBag.movieGenre = new SelectList(GenreLst, "Comedy");
运行应用程序,并浏览到 /Movies/Index。 按流派、 电影名称和这两个条件,请尝试搜索。
在本部分中创建了搜索操作方法和视图,以让用户搜索电影标题和流派。 在下一部分中,将探讨如何将属性添加到Movie
模型以及如何添加初始值设定项将自动创建测试数据库。