在本节中,您将添加搜索功能到Index操作方法,这样您能够通过电影类型或名称来搜索电影。
更新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);
}
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表达式。Lambdas用于基于方法的LINQ查询参数标准查询运算符方法,正如上述方法的代码。LINQ查询时不执行他们定义的或修改Where或OrderBy
等方法。相反,查询执行延迟,这意味着一个表达式的评价是推迟到其实现价值实际上是迭代或ToList方法被调用。在搜索示例中,执行查询的 Index.cshtml视图。关于延迟查询执行的更多信息,请参阅查询执行。注:包含方法在数据库上运行,而不是上面的c#代码。在数据库,包含映射到SQL,不分大小写。
现在你可以更新Index视图将显示给用户。
运行应用程序并导航到 /Movies/Index。追加一个查询字符串,如?searchString=ghost的URL,显示过滤后的电影。
如果你改变的Index方法有一个参数命名为id,id参数匹配{ id }占位符中设置的默认路由App_Start\RouteConfig.cs文件。
{controller}/{action}/{id}
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方法来测试如何传递route-bound 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的作用是当用户点击过滤按钮提交时表单form发布自己。
Visual Studio 2013在显示和编辑视图文件时有一个很好的改善,当您运行应用程序打开一个视图文件,Visual Studio 2013调用正确的控制器操作方法来显示视图。
在Visual Studio中打开Index视图(如上图所示),利用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>";
}
然而,即使你添加这个HttpPost版本的Index方法,有一个限制在都是如何实现的。想象一下你想收藏一个特定搜索或者您想要发送一个链接给朋友,他们可以点击为了看到相同的过滤列表的电影。注意到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包含一个搜索查询字符串。搜索也会去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;
通用列表的代码使用AddRange方法收集所有不同类型添加到列表中。(没有Distinct修饰词,重复类型将被添加——例如,喜剧会添加两次在我们的样例)。然后,代码存储ViewBag.movieGenre对象中的类型的列表。存储类数据(比如一个电影流派)作为ViewBag SelectList对象,然后访问类别下拉列表框中的数据,是一个典型的MVC应用程序的方法。
下面的代码显示了如何检查movieGenre参数。如果它不是空的,代码进一步限制了电影的代码查询,限制选择的电影为指定的类型。
if (!string.IsNullOrEmpty(movieGenre))
{
movies = movies.Where(x => x.Genre == movieGenre);
}
如前所述,并不是运行在数据库的查询,而是直到电影遍历列表完成(视图中发生,在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")
参数“movieGenre”为 DropDownList在 ViewBag中找到 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")
在我们的数据库中有一个电影“ Comedy”风格,“ Comedy”将预选的下拉列表。因为我们没有一个电影流派“ All”,在 SelectList中没有“ All”,所以当我们回来后没有做一个选择, movieGenre查询字符串值是空的。
运行应用程序和浏览/Movies/Index。试着搜索类型,电影名称和标准。
在本节中,您创建了一个search动作方法和观点,让用户搜索电影标题和流派。在下一节中,您将看看如何将属性添加到电影模型以及如何添加一个初始化,将自动创建一个测试数据库。