There can be no Triumph without Loss,No Victory without Suffering,No Freedom without Sacrifice.
All you have to decide is what to do with the time that is given to you.
Get busy Living, or Get busy Dying?
  首页 | 留言给我 | 订阅 Rss | CLI | 黄白之恋 Posts:158   Hits: 5545884    Comments: 173    
 日历归档
<<  <  2024 - 11  >  >>
SuMoTuWeThFrSa
     12
3456789
10111213141516
17181920212223
24252627282930
 About Me
 Name: ZhangSichu
 Sex: Male
 Age: 32
 Email: ZhangSichu@gmail.com
 MSN: ZhangSichu@hotmail.com
 Home: ZhangSichu.com
 WeiBo: weibo.com/zhangsichu
 个人推荐
 分类归档
  ·C++/C(5)  RSS
  ·软件工程(1)  RSS
  ·杂事/随感(26)  RSS
  ·.Net/Java(30)  RSS
  ·面向对象程序设计(5)  RSS
  ·汇编/破解(0)  RSS
  ·平面设计(3)  RSS
  ·SQL(5)  RSS
  ·COM/COM+(2)  RSS
  ·Web开发(81)  RSS
 My Friends
Back Forward Refresh Home 2024年11月23日 星期六 RSS CLI Mine Sweeper. In Javascript.

  [翻译] 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。筛选的影片会被显示。
Click to Open in New Window

如果你改变了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段)的标题搜索了,而不是作为查询字符串值,截图如下:
Click to Open in New Window

然而,你不能期望用户可以每次要搜索一部电影都会去修改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的将调用正确的控制器操作方法来展示视图。
Click to Open in New Window

在Visual Studio中打开使用Index视图(在上面的图片所示),点击Ctr F5或F5运行应用程序,然后试试搜索一部电影。
Click to Open in New Window

该Index 方法的HttpPost没有重载。 你不需要它,因为该方法不改变application的状态,只是过滤数据。

您可以添加以下httppost Index方法。在这种情况下,函数调用将匹配的HttpPost Index方法,的HttpPost Index方法运行的如下面的图片所示。

[HttpPost]
public string Index(FormCollection fc, string searchString)
{
return "<h3> From [HttpPost]Index: " + searchString + "</h3>";
}

Click to Open in New Window

但是,即使您添加此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))

Click to Open in New Window

现在当您提交搜索,该 URL 将包含搜索的查询字符串(query string)。搜索还会请求到 HttpGet Index操作方法,即使您也有一个HttpPost Index方法。
Click to Open in New Window

按照电影流派添加搜索
如果您添加了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。尝试搜索流派,电影名称,并同时选择这两个条件。
Click to Open in New Window

在本节中,您创建了一个搜索的方法和视图,使用它,用户可以通过电影标题和流派来搜索。在下一节中,您将看到如何添加一个属性到Movie model,和如何添加一个初始值设定项值,它会自动创建一个测试数据库。
  Posted @ 5/19/2015 11:16:28 AM | Hits (6184) | Comment (0

  Post Comment
标题 *
作者 *
密码 记住我
评论 *
    


Stable in Firefox 1.5 2.0Stable in IE6 IE7Stable in MozillaStable in Netscape
ZhangSichu.com V0.1.7507
Powered By ZhangSichu
Copyright © ZhangSichu
Download ZhangSichu.com source code. Download source code