学习ASP.NET MVC 编程系列目录 html
学习ASP.NET MVC(一)——个人第一个ASP.NET MVC应用程序 sql
学习ASP.NET MVC(二)——个人第一个ASP.NET MVC 控制器 数据库
学习ASP.NET MVC(三)——个人第一个ASP.NET MVC 视图 编程
学习ASP.NET MVC(四)——个人第一个ASP.NET MVC 实体对象 浏览器
学习ASP.NET MVC(五)——个人第一个ASP.NET MVC CURD页面 工具
学习ASP.NET MVC(六)——个人第一个ASP.NET MVC 编辑页面 post
学习ASP.NET MVC(七)——个人第一个ASP.NET MVC 查询页面 学习
学习ASP.NET MVC(八)——“Code First Migrations ”工具 spa
学习ASP.NET MVC(九)——“Code First Migrations ”工具使用示例 3d
在本篇文章中,我将添加一个新的查询页面(SearchIndex),能够按书籍的种类或名称来进行查询。这个新页面的网址是http://localhost:36878/Book/ SearchIndex。该页面中用一个下拉框来显示种类,用一文本框让用户输入书籍的名称。当用户在点击“查询”按钮以后,页面会被刷新,显示用户的查询结果。控制器会根据用户提交查询参数,由动做方法(Action Motehd)去解析用户提交的参数值,并使用这些值来查询数据库。
第一步,建立SearchIndex查询页面
首先,在BookController中添加一个SearchIndex动做方法。该方法将返回一个包含HTML表单的视图。代码以下:
public ActionResult SearchIndex(string searchString) { var books = from m in db.Books select m; if (!String.IsNullOrEmpty(searchString)) { books = books.Where(s => s.Name.Contains(searchString)); } return View(books); }
上面SearchIndex方法代码中的第一行以下面,其做用是建立一个LINQ查询从数据库中筛选相应的书籍数据:
var books = from m in db.Books select m;
这一句表示查询已经创建,可是还没有对数据存储区中的数据进行筛选。
若是“searchString”参数变量中有一个字符串,则这个“books”查询语句将以“searchString”参数变量的值作为查询条件进行筛选相应的书籍数据,以下面的代码:
if (!String.IsNullOrEmpty(searchString)) { books = books.Where(s => s.Name.Contains(searchString)); }
上面代码中的s =>s.Title代码是一个Lambda表达式。 Lambda 表达式用在基于方法的 LINQ 查询中,做为诸如 Where 和 Where 等标准查询运算符方法的参数。 例如上面的代码中使用的方法。LINQ查询时未执行它们的定义,或者当他们经过调用一个方法进行修改,或在排序时进行修改。相反,查询执行的延迟,这意味着一个表达式的计算被延迟,直到其变量实际上的迭代结束或者能够调用的方法(ToList方法)被调用。在SearchIndex这个页面中,查询是在SearchIndex视图下执行。
接下来,咱们来制做一个SearchIndex视图,以将这个查询界面呈现给用户看。在Visual Studio中的BookController文件中右键单击里面的SearchIndex方法,在弹出菜单中单击“添加视图”菜单。在添加视图对话框中,指定你要一个Book对象传递给视图模板做为它的模型类。在支架模板列表中,选择列表,而后单击“添加”。以下图。
当单击“添加”按钮,将建立一个Views\Book\ SearchIndex.cshtml视图模板。由于你选择了列表中的支架模板列表中,Visual Studio会自动生成(搭建)的视图中的一些默认的标记。基架建立一个HTML表单。它检查Book类和建立的代码来呈现为类的每一个属性<label>元素。下面的清单显示生成的建立视图:
@model IEnumerable<MvcApplication1.Models.Book> @{ ViewBag.Title = "书籍查询"; } <h2>书籍查询</h2> <p> @Html.ActionLink("Create New", "Create") </p> <table> <tr> <th> @Html.DisplayNameFor(model => model.Category) </th> <th> @Html.DisplayNameFor(model => model.Name) </th> <th> @Html.DisplayNameFor(model => model.Numberofcopies) </th> <th> @Html.DisplayNameFor(model => model.AuthorID) </th> <th> @Html.DisplayNameFor(model => model.Price) </th> <th> @Html.DisplayNameFor(model => model.PublishDate) </th> <th></th> </tr> @foreach (var item in Model) { <tr> <td> @Html.DisplayFor(modelItem => item.Category) </td> <td> @Html.DisplayFor(modelItem => item.Name) </td> <td> @Html.DisplayFor(modelItem => item.Numberofcopies) </td> <td> @Html.DisplayFor(modelItem => item.AuthorID) </td> <td> @Html.DisplayFor(modelItem => item.Price) </td> <td> @Html.DisplayFor(modelItem => item.PublishDate) </td> <td> @Html.ActionLink("Edit", "Edit", new { id=item.BookID }) | @Html.ActionLink("Details", "Details", new { id=item.BookID }) | @Html.ActionLink("Delete", "Delete", new { id=item.BookID }) </td> </tr> } </table>
按F5, 运行该应用程序,并使用浏览器导航到/Book/ SearchIndex。在URL后面会追加一个查询字符串,如“?searchString=sql”。提交以后,符合条件的书籍数据将显示。以下图。
第三,修改SearchIndex查询方法
咱们也能够修改SearchIndex方法的参数,传入一个命名参数“ID”,这个“ID”参数将匹配在Global.asax文件中的缺省路由设置中的{id}占位符。路由设置以下:
{controller}/{action}/{id}
原来SearchIndex方法以下所示:
public ActionResult SearchIndex(string searchString) { var books = from m in db.Books select m; if (!String.IsNullOrEmpty(searchString)) { books = books.Where(s => s.Name.Contains(searchString)); } return View(books); }
修改后的SearchIndex方法将以下所示:
public ActionResult SearchIndex(string id) { string searchString = id; var books = from m in db.Books select m; if (!String.IsNullOrEmpty(searchString)) { books = books.Where(s => s.Name.Contains(searchString)); } return View(books); }
如今,您能够把查询条件“书籍名称”做为路由数据(URL中的一段字符),而不是做为查询字符串值。以下图。
第三,添加“书籍名称”查询条件
经过上面的学习,咱们实现了数据查询功能。可是咱们不能但愿普通用户也能像咱们同样,会在URL中添加查询条件。当须要进行查询时,本身去修改URL中的查询条件内容来进行书籍查询。因此,须要添加一个查询页面,方便普通用户输入相应的查询条件,根据查询条件去查询书籍。
1、改变SearchIndex方法的签名,并经过路由绑定到ID参数上,让SearchIndex方法接受一个名为“searchString”字符串做为参数。代码以下:
public ActionResult SearchIndex(string searchString) { var books = from m in db.Books select m; if (!String.IsNullOrEmpty(searchString)) { books = books.Where(s => s.Name.Contains(searchString)); } return View(books); }
2、打开Views\Book\ SearchIndex.cshtml文件,在@Html.ActionLink("Create New", "Create")的位置处,添加一个文本框与一个查询按钮。内容以下:
@using (Html.BeginForm()) { <p> 书籍名称: @Html.TextBox("SearchString")<br /> <input type="submit" value="查询" /></p> }
下面的代码显示了Views\Book\ SearchIndex.cshtml文件的一部分与增长的筛选标记。
@Model IEnumerable<MvcApplication1.Models.Book> @{ ViewBag.Title = "书籍查询"; } <h2>书籍查询</h2> @using (Html.BeginForm()) { <p> 书籍名称: @Html.TextBox("SearchString")<br /> <input type="submit" value="查询" /></p> }
这个Html.BeginForm辅助方法建立了一个<form>标签。当用户经过单击“查询”按钮提交表单时,Html.BeginForm辅助方法将会把这个Form中的内容提交给控制器,同时刷新页面。
3、按F5,运行该应用程序,并在“书籍名称”文本框中输入“sql”,而后点击“查询”按钮,进行书籍查询。以下图。
还有不须要重载SearchIndex的HttpPost的方法。由于该方法不改变应用程序的状态,只是是用来查询数据。
你能够象下面同样把[HttpPost]加在SearchIndex方法的上面。在添加了[HttpPost]以后,浏览器将首先调用匹配HttpPost的SearchIndex方法。HttpPost的SearchIndex方法运行结果以下图。
[HttpPost] public string SearchIndex(FormCollection fc, string searchString) { return "<h3> From [HttpPost]SearchIndex: " + searchString + "</h3>"; }
然而,即便添加了SearchIndex的HttpPost版本的方法。假设一下以下场景,你想把某个查询结果发给你的朋友,你又想只发一个特定连接给朋友,让他们能够查询查看相同的一个查询结果。请注意,若是是相同的查询结果,一个为HTTP POST请求,另外一个为相同的URL GET请求(例如本地主机:XXXXX /图书/ SearchIndex ) 。则HTTP POST请求在URL自己没有带查询参数的状况下,是没法看到查询结果的。若是只是一个URL,这就意味着你与朋友们永远不能看到相同的查询结果。
你应该使用如下的解决方案,使用BeginForm的重载方法,指定POST请求应该在URL中添加的相应的查询参数信息 ,它应该被路由到SearchIndex方法的HTTPGET版本。使用下面的代码替换现有参数的BeginForm方法将:以下图。
@using (Html.BeginForm("SearchIndex", "book", FormMethod.Get))
如今,当你点击“查询”按钮时,URL中将包含查询条件的字符串。查询请求也将去请求HTTPGET的 SearchIndex操做方法,即便你有一个HttpPost的SearchIndex方法。以下图。
第三,添加“书籍种类”查询方法
第一步,删除代码中HttpPost版本的SearchIndex方法。
第二步,添加新的查询功能。在页面中添加一个“书籍种类”的查询条件,让用户能够经过“书籍种类”查询到相关书籍。用下面的代码替换SearchIndex方法:
public ActionResult SearchIndex(string Category, string searchString) { var cateLst = new List<string>(); var cateQry = from d in db.Books orderby d.Category select d.Category; cateLst.AddRange(cateQry.Distinct()); ViewBag.category = new SelectList(cateLst); var books = from m in db.Books select m; if (!String.IsNullOrEmpty(searchString)) { books = books.Where(s => s.Name.Contains(searchString)); } if (string.IsNullOrEmpty(Category)) return View(books); else { return View(books.Where(x => x.Category == Category)); } }
这个新的SearchIndex方法增长了一个新的查询条件,即Category。代码的前几行建立一个List对象从数据库中查询“书籍种类”,并将查询到的结果添加到List对象中。
下面的代码是经过一个LINQ查询从数据库把全部书籍种类都查了出来。
var cateQry = from d in db.Books orderby d.Category select d.Category;
如下代码的做用是使用泛型List集合的AddRange方法全部书籍类型添加到列表中。 (若是没有DISTINCT修饰符,会将相同的类型增长到列表中 - 例如,MS,SAP将会被咱们添加两次)。
cateLst.AddRange(cateQry.Distinct());
而后,该代码存储在ViewBag对象流派列表。
ViewBag.category = new SelectList(cateLst);
下面的代码演示如何检查Category参数。若是它不是空的,该代码进一步限制了书的查询所选择的书限制到指定的种类。
if (string.IsNullOrEmpty(Category)) return View(books); else { return View(books.Where(x => x.Category == Category)); }
第四,在SearchIndex查询页面中添加“书籍种类”查询条件
添加一个HTML样式的下拉列表框(DropDownList)到Views\Book\ SearchIndex.cshtml文件中,放在“书籍名称”文本框的前面。已完成的代码以下所示:
<p> @using (Html.BeginForm("SearchIndex","book",FormMethod.Get)){ <p>书籍种类: @Html.DropDownList("category", "All") 书籍名称: @Html.TextBox("SearchString") <input type="submit" value="查询" /></p> } </p>
按F5,运行这个应用程序,在浏览器中浏览/Book/ SearchIndex这个地址。就能够按“书籍种类”、“书籍名称”进行书籍信息查询。以下图1,图2。
图1
图2
在本篇中学习如何建立一个新的查询操做方法和视图,让用户经过书籍名称和书籍类型来进行查询。