搜索
注意
此处使用最新版本的 Visual Studio 提供了本教程的更新版本。 新教程使用 ASP.NET Core MVC,这比本教程提供了许多改进。
本教程介绍具有控制器和视图的 ASP.NET Core MVC。 Razor Pages 是 ASP.NET Core 中的一种新替代方法,它是一种基于页面的编程模型,可简化 Web UI 的生成过程并提高效率。 建议先尝试 Razor 页面教程,再使用 MVC 版本。 Razor 页面教程:
- 易于关注。
- 涵盖更多功能。
- 是新应用开发的首选方法。
添加搜索方法和搜索视图
在本部分中,你将向操作方法添加搜索功能 Index
,以便按流派或名称搜索电影。
先决条件
若要匹配本部分的屏幕截图,需要 (F5) 运行应用程序,并将以下电影添加到数据库。
标题 | 发布日期 | 流派 | 价格 |
---|---|---|---|
鬼怪 | 6/8/1984 | 喜剧 | 6.99 |
幽灵怪人 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 查询中用作标准查询运算符方法的参数,例如上述代码中使用的 Where 方法。 在定义 LINQ 查询或通过调用 或 OrderBy
等Where
方法进行修改时,不会执行 LINQ 查询。 相反,查询执行是延迟的,这意味着表达式的计算会延迟,直到实际循环访问其实现的值或 ToList
调用 方法。 在 Search
示例中,查询在 Index.cshtml 视图中执行。 有关延迟执行查询的详细信息,请参阅Query Execution(查询执行)。
现在,可以更新 Index
将窗体显示给用户的视图。
运行应用程序并导航到 /Movies/Index。 将查询字符串(如 ?searchString=ghost
)追加到 URL。 筛选的电影将显示出来。
如果将 方法的 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。 因此需要添加 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);
}
打开 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
通过单击“ 筛选 ”按钮提交表单时,帮助程序会使表单发布到自己。
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 请求的 URL 相同, (localhost:xxxxx/Movies/Index) -- 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
将帮助程序添加到 Views\Movies\Index.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”为帮助程序提供了在 中ViewBag
查找 IEnumerable<SelectListItem>
的键DropDownList
。 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”提供选项标签。 如果在浏览器中检查该选项,将看到其“value”属性为空。 由于控制器仅筛选 if
字符串不 null
为空或为空,因此提交一 movieGenre
个空值会显示所有流派。
还可以将选项设置为默认选中。 如果希望将“喜剧”作为默认选项,可以按如下所示更改控制器中的代码:
ViewBag.movieGenre = new SelectList(GenreLst, "Comedy");
运行应用程序并浏览到 /Movies/Index。 尝试按流派、电影名称和这两个条件进行搜索。
在本部分中,你创建了一个搜索操作方法和视图,使用户能够按电影标题和流派进行搜索。 在下一部分中,你将了解如何向模型添加属性 Movie
,以及如何添加自动创建测试数据库的初始值设定项。