9.1 实现数据的明细信息视图
首先,让我们来看一下如何实现一条数据的明细信息视图。为了更好地体会这一功能,首先我们在前文所述的电影清单视图(Views文件夹下面的Movies文件夹下面的Index.cshtml文件)中删除电影清单中的种类、票价、电影等级字段,使其代码如代码清单9-1中所示。
代码清单9-1 修改后的Index.cshtml文件
[html] view plain copy print ?
- @model IEnumerable<MvcMovie.Models.Movie>
-
- @{
-
- ViewBag.Title = "电影清单";
-
- }
-
- <h2>我的电影清单</h2>
-
- <p>
-
- @Html.ActionLink("追加", "Create")
-
- </p>
-
- <table>
-
- <tr>
-
- <th></th>
-
- <th>
-
- 电影名称
-
- </th>
-
- <th>
-
- 发行日期
-
- </th>
-
- </tr>
-
- @foreach (var item in Model) {
-
- <tr>
-
- <td>
-
- @Html.ActionLink("编辑", "Edit", new { id=item.ID }) |
-
- @Html.ActionLink("查看明细", "Details", new { id=item.ID }) |
-
- @Html.ActionLink("删除", "Delete", new { id=item.ID })
-
- </td>
-
- <td>
-
- @item.Title
-
- </td>
-
- <td>
-
- @String.Format("{0:d}", item.ReleaseDate)
-
- </td>
-
- </tr>
-
- }
-
- </table>
@model IEnumerable<MvcMovie.Models.Movie> @{ ViewBag.Title = "电影清单"; } <h2>我的电影清单</h2> <p> @Html.ActionLink("追加", "Create") </p> <table> <tr> <th></th> <th> 电影名称 </th> <th> 发行日期 </th> </tr> @foreach (var item in Model) { <tr> <td> @Html.ActionLink("编辑", "Edit", new { id=item.ID }) | @Html.ActionLink("查看明细", "Details", new { id=item.ID }) | @Html.ActionLink("删除", "Delete", new { id=item.ID }) </td> <td> @item.Title </td> <td> @String.Format("{0:d}", item.ReleaseDate) </td> </tr> } </table>
重新运行该应用程序,在浏览器中输入地址“http://localhost:xx/Movies”,浏览器中运行结果如图9-1所示。
图9-1 修改后的电影清单画面
现在电影清单画面中就只显示每条数据的电影名称与发行日期了,如果像查看该条数据的详细信息,需要点击每条数据的“查看明细”链接,将画面导航到明细数据画面,在该画面中查看这条数据的明细信息。当一条数据的细节信息比较多,而我们只想在该数据的列举清单中显示该数据的几个摘要信息,通过点击链接或按钮的操作来查看数据的细节信息时这种处理方法是比较有用的。
接下来让我们来追加这个明细数据视图。首先打开Movie控制器,追加一个返回明细数据视图的Details方法,代码如下所示。
[csharp] view plain copy print ?
-
-
-
-
- public ActionResult Details(int id)
-
- {
-
- Movie movie = db.Movies.Find(id);
-
- if (movie == null)
-
- return RedirectToAction("Index");
-
- return View("Details", movie);
-
- }
// // GET: /Movies/Details public ActionResult Details(int id) { Movie movie = db.Movies.Find(id); if (movie == null) return RedirectToAction("Index"); return View("Details", movie); }
code-first通过使用Find方法来让一条数据的寻找变得非常容易。这个方法的一个非常重要的安全特性就是我们可以确保我们寻找的是一条可以被映射为Movie对象的数据。为什么这种做法可以确保安全性呢?举个例子来说,一个黑客可以将“http://localhost:xxxx/Movies/Details/1”地址修改为“http://localhost:xxxx/Movies/Details/12345”,如果数据库中没有这条id为12345的数据,根据以上代码所示,作为寻找结果的Movie对象将被设定为null,浏览器将重新返回显示电影清单画面。
在Details方法中点击鼠标右键,选择“添加视图”,依然勾选“创建强类型视图”,模型类选择Movie,在支架模板中选择“Details”(明细数据),如图9-2所示。
图9-2 添加明细数据视图
如果要创建中文网站或应用程序,则将默认生成的Details.cshtml文件中有关英文文字修改为中文,修改完毕后该文件中的代码如代码清单9-2中所示。
代码清单9-2 Details.cshtml文件(明细数据视图)中的代码
[html] view plain copy print ?
- @model MvcMovie.Models.Movie
-
- @{
-
- ViewBag.Title = "电影详细信息";
-
- }
-
- <h2>电影详细信息</h2>
-
- <fieldset>
-
- <legend>电影</legend>
-
- <div class="display-label">标题</div>
-
- <div class="display-field">@Model.Title</div>
-
- <div class="display-label">发行日期</div>
-
- <div class="display-field">@String.Format("{0:d}",
-
- Model.ReleaseDate)</div>
-
- <div class="display-label">种类</div>
-
- <div class="display-field">@Model.Genre</div>
-
- <div class="display-label">票价</div>
-
- <div class="display-field">@String.Format("{0:c2}", Model.Price)</div>
-
- <div class="display-label">等级</div>
-
- <div class="display-field">@Model.Rating</div>
-
- </fieldset>
-
- <p>
-
- @Html.ActionLink("编辑", "Edit", new { id=Model.ID }) |
-
- @Html.ActionLink("返回电影清单", "Index")
-
- </p>
@model MvcMovie.Models.Movie @{ ViewBag.Title = "电影详细信息"; } <h2>电影详细信息</h2> <fieldset> <legend>电影</legend> <div class="display-label">标题</div> <div class="display-field">@Model.Title</div> <div class="display-label">发行日期</div> <div class="display-field">@String.Format("{0:d}", Model.ReleaseDate)</div> <div class="display-label">种类</div> <div class="display-field">@Model.Genre</div> <div class="display-label">票价</div> <div class="display-field">@String.Format("{0:c2}", Model.Price)</div> <div class="display-label">等级</div> <div class="display-field">@Model.Rating</div> </fieldset> <p> @Html.ActionLink("编辑", "Edit", new { id=Model.ID }) | @Html.ActionLink("返回电影清单", "Index") </p>
重新运行应用程序,在电影清单画面中点击某个电影的“查看明细”链接,浏览器显示画面如图9-3所示。
图9-3 电影细节信息画面
9.2 实现数据的修改视图
接下来,让我们来看一下如何实现一个用来修改数据的视图。
首先打开Movie控制器,追加一个返回数据修改视图的Edit方法与一个对该视图中的表单提交进行处理的Edit方法,代码如下所示。
[csharp] view plain copy print ?
-
-
-
-
- public ActionResult Edit(int id)
-
- {
-
- Movie movie = db.Movies.Find(id);
-
- if (movie == null)
-
- return RedirectToAction("Index");
-
-
-
- return View(movie);
-
- }
-
-
-
-
-
- [HttpPost]
-
- public ActionResult Edit(Movie model)
-
- {
-
- try
-
- {
-
- var movie = db.Movies.Find(model.ID);
-
-
-
- UpdateModel(movie);
-
- db.SaveChanges();
-
- return RedirectToAction("Details", new { id = model.ID });
-
- }
-
- catch (Exception)
-
- {
-
- ModelState.AddModelError("", "修改失败,请查看详细错误信息。");
-
- }
-
-
-
- return View(model);
-
- }
// // GET: /Movies/Edit public ActionResult Edit(int id) { Movie movie = db.Movies.Find(id); if (movie == null) return RedirectToAction("Index"); return View(movie); } // // POST: /Movies/Edit [HttpPost] public ActionResult Edit(Movie model) { try { var movie = db.Movies.Find(model.ID); UpdateModel(movie); db.SaveChanges(); return RedirectToAction("Details", new { id = model.ID }); } catch (Exception) { ModelState.AddModelError("", "修改失败,请查看详细错误信息。"); } return View(model); }
这两个Edit方法中,第一个方法将在用户点击外部画面的“编辑”链接时被调用,用来在浏览器中显示数据修改视图,并且在该视图中显示用户选择编辑的数据。第二个Edit方法前面带有一个[HttpPost]标记,负责将修改数据视图中提交的表单数据绑定到一个用模型创建出来的Movie对象实例之上(当用户在表单中完成数据修改并点击保存按钮的时候进行提交),UpdateModel(movie)方法将调用模型拷贝器,该模型拷贝器将修改后的数据(使用model参数,该参数指向一个各属性值为编辑后数据的Movie对象实例)拷贝到数据库中(即为数据的保存过程)。在保存数据的过程中如果发生任何错误而导致保存失败的话,则画面重新返回到数据修改视图。
接下来让我们来追加该数据修改视图、在Edit方法中点击鼠标右键,选择“添加视图”,依然勾选“创建强类型视图”,模型类选择Movie,在支架模板中选择“Edit”(修改数据),如图9-4所示。
图9-4 追加数据修改视图
如果要创建中文网站或应用程序,则将默认生成的Edit.cshtml文件中有关英文文字修改为中文,修改完毕后该文件中的代码如代码清单9-3中所示。
代码清单9-3 Edit.cshtml文件(修改数据视图)中的代码
@model MvcMovie.Models.Movie @{ ViewBag.Title = "修改电影信息"; } <h2>修改电影信息</h2> <script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script> <script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script> @using (Html.BeginForm()) { @Html.ValidationSummary(true) <fieldset> <legend>电影</legend> @Html.HiddenFor(model => model.ID) <div class="editor-label"> 标题 </div> <div class="editor-field"> @Html.EditorFor(model => model.Title) @Html.ValidationMessageFor(model => model.Title) </div> <div class="editor-label"> 发行日期 </div> <div class="editor-field"> @Html.EditorFor(model => model.ReleaseDate) @Html.ValidationMessageFor(model => model.ReleaseDate) </div> <div class="editor-label"> 种类 </div> <div class="editor-field"> @Html.EditorFor(model => model.Genre) @Html.ValidationMessageFor(model => model.Genre) </div> <div class="editor-label"> 票价 </div> <div class="editor-field"> @Html.EditorFor(model => model.Price) @Html.ValidationMessageFor(model => model.Price) </div> <div class="editor-label"> 电影等级 </div> <div class="editor-field"> @Html.EditorFor(model => model.Rating) @Html.ValidationMessageFor(model => model.Rating) </div> <p> <input type="submit" value="保存" /> </p> </fieldset> } <div> @Html.ActionLink("返回电影清单", "Index") </div>
重新运行应用程序,在电影清单画面中点击某个电影的“编辑”链接,浏览器显示画面如图9-5所示。
图9-5 数据修改视图
在该视图中修改选中的数据,然后点击保存按钮,浏览器将修改后的数据显示在明细数据视图中,如图9-6所示。
图9-6 数据修改完成后被显示在明细数据视图中
9.3 实现数据的删除视图
接下来,让我们来看一下如何实现一个用来删除数据的视图。
首先打开Movie控制器,追加一个返回数据修改视图的Edit方法与一个对该视图中的表单提交进行处理的Edit方法,代码如下所示。
[csharp] view plain copy print ?
-
-
-
-
- public ActionResult Delete(int id)
-
- {
-
- Movie movie = db.Movies.Find(id);
-
- if (movie == null)
-
- return RedirectToAction("Index");
-
-
-
- return View(movie);
-
- }
-
-
-
-
-
- [HttpPost]
-
- public RedirectToRouteResult Delete(int id,FormCollection collection)
-
- {
-
- var movie = db.Movies.Find(id);
-
- db.Movies.Remove(movie);
-
- db.SaveChanges();
-
- return RedirectToAction("Index");
-
- }
// //GET: /Movies/Delete public ActionResult Delete(int id) { Movie movie = db.Movies.Find(id); if (movie == null) return RedirectToAction("Index"); return View(movie); } // // POST: /Movies/Delete [HttpPost] public RedirectToRouteResult Delete(int id,FormCollection collection) { var movie = db.Movies.Find(id); db.Movies.Remove(movie); db.SaveChanges(); return RedirectToAction("Index"); }
这里请注意第一个没有[HttpPost]标记的Delete方法并不会将数据删除,因为如果通过GET请求而删除(或者追加、修改)删除数据的话都会打开一个安全漏洞。
接下来让我们来追加该数据删除视图、在Delete方法中点击鼠标右键,选择“添加视图”,依然勾选“创建强类型视图”,模型类选择Movie,在支架模板中选择“Delete”(删除数据),如图9-7所示。
图9-7 追加数据删除视图
如果要创建中文网站或应用程序,则将默认生成的Delete.cshtml文件中有关英文文字修改为中文,修改完毕后该文件中的代码如代码清单9-3中所示。
代码清单9-3 Delete.cshtml文件(删除数据视图)中的代码
[html] view plain copy print ?
- @model MvcMovie.Models.Movie
-
-
-
- @{
-
- ViewBag.Title = "删除电影数据";
-
- }
-
-
-
- <h2>删除电影数据</h2>
-
-
-
- <h3>你确实想将这条电影数据删除吗?</h3>
-
- <fieldset>
-
- <legend>电影</legend>
-
-
-
- <div class="display-label">标题</div>
-
- <div class="display-field">@Model.Title</div>
-
-
-
- <div class="display-label">发行日期</div>
-
- <div class="display-field">@String.Format("{0:d}",
-
- Model.ReleaseDate)</div>
-
- <div class="display-label">种类</div>
-
- <div class="display-field">@Model.Genre</div>
-
- <div class="display-label">票价</div>
-
- <div class="display-field">@String.Format("{0:F}", Model.Price)</div>
-
- <div class="display-label">电影等级</div>
-
- <div class="display-field">@Model.Rating</div>
-
- </fieldset>
-
- @using (Html.BeginForm()) {
-
- <p>
-
- <input type="submit" value="删除" /> |
-
- @Html.ActionLink("返回电影清单", "Index")
-
- </p>
-
- }
@model MvcMovie.Models.Movie @{ ViewBag.Title = "删除电影数据"; } <h2>删除电影数据</h2> <h3>你确实想将这条电影数据删除吗?</h3> <fieldset> <legend>电影</legend> <div class="display-label">标题</div> <div class="display-field">@Model.Title</div> <div class="display-label">发行日期</div> <div class="display-field">@String.Format("{0:d}", Model.ReleaseDate)</div> <div class="display-label">种类</div> <div class="display-field">@Model.Genre</div> <div class="display-label">票价</div> <div class="display-field">@String.Format("{0:F}", Model.Price)</div> <div class="display-label">电影等级</div> <div class="display-field">@Model.Rating</div> </fieldset> @using (Html.BeginForm()) { <p> <input type="submit" value="删除" /> | @Html.ActionLink("返回电影清单", "Index") </p> }
在电影清单画面中点击一条数据的删除按钮,浏览器打开数据删除视图,如图9-8所示。
图9-8 数据删除视图
点击删除按钮,该条数据将被删除,浏览器中返回显示电影清单画面。
最后,我们来回顾一下本教程中所讲述的内容。本教程中首先讲述了如何创建控制器、视图、如何将控制器中的数据传递给视图。然后我们设计并创建了一个数据模型。code-first根据模型在指定的数据库服务器中创建了一个数据库。我们可以从这个数据库中获取数据并显示在一个HTML表格中。然后我们追加了一个添加数据所用的视图。接下来我们通过添加一个数据列(也称字段)的方式来改变数据表,同时修改了数据清单画面与数据追加视图来显示这个新追加的数据列。然后我们通过使用DataAnnotations命名空间,为数据模型标注属性的方式来追加了一些数据验证规则。这些数据验证即可以在客户端实现,也可以在服务器端实现。最后,我们添加代码与视图模板来创建了数据的修改视图,删除视图与明细数据视图。
接下来,我鼓励你继续看笔者即将发表的“MVC书店”这篇连载教程,来进一步了解一下ASP.NET MVC的实现方法。