在本节中我们将要在数据库中追加并保存一些数据。我们将要创建一个表单以及一些表单输入控件,用来输入数据信息。当用户提交表单时将把这些用户输入的信息 保存在数据库中。我们可以通过在浏览器中输入“http://localhost:xx/Movies/Create”这个URL地址来访问这个表单。
6.1 显示追加信息时所用表单
首先,我们需要在我们的MoviesController类中追加一个Create方法,该方法返回一个视图,该视图中包含了用户输入信息时所要用到的表单。
public ActionResult Create()
{
return View();
}
现在让我们来实现这个Create方法中所要返回的视图,我们将在这个视图中向用户显示追加数据时所需要用到的表单。在Create方法中点击鼠标右键,并点击上下文菜单中的“添加视图”。
在“添加视图”对话框中选择“创建强类型视图”,将模型类指定为“Movie”,在支架模板中选择Create,如图6-1所示。
图6-1 添加追加数据时所用视图
点击添加按钮,Views文件夹下的Movies文件夹中将会自动添加一个名为“Create.cshtml”的视图模板文件。因为你在支架模板中选择了“Create”,所以支架模板会在该视图模板文件中自动生成一些默认代码。打开该文件进行查看,在该文件中已经自动创建了一个HTML表单,以及一段用来显示校验时错误信息的文字。Visual Web Developer检查Movies类,并自动创建与该类中每个属性相对应的<label>元素以及<input>元素。支架模板自动生成的创建数据所用视图中的代码如代码清单6-1所示。
代码清单6-1 支架模板自动生成的创建数据所用视图中的代码
@model MvcMovie.Models.Movie
@{
ViewBag.Title = "Create";
}
<h2>Create</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>Movie</legend>
<div class="editor-label">
@Html.LabelFor(model => model.Title)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Title)
@Html.ValidationMessageFor(model => model.Title)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.ReleaseDate)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.ReleaseDate)
@Html.ValidationMessageFor(model => model.ReleaseDate)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.Genre)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Genre)
@Html.ValidationMessageFor(model => model.Genre)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.Price)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Price)
@Html.ValidationMessageFor(model => model.Price)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
这段代码中使用了几个HTML帮助器的方法来帮助简化HTML标签的书写方法。Html.LabelFor帮助器用于显示字段名 (”Title”,”ReleaseDate”,”Genre”或者”Price”)。Html.EditorFor帮助器用于显示一个提供给用户输入信 息的HTML的<input>元素。Html.ValidationMessageFor帮助器用于显示一个针对属性的校验信息。请注意我们 的视图模板的顶部有一个“@model MvcMovie.Models.Movie”的声明,该声明将我们的视图模板中的“模型”强类型化成一个Movie类。
运行应用程序,在浏览器中输入“http://localhost:xx/Movies/Create”,浏览器中显示如图6-2所示。
图6-2 支架模板自动生成的视图
在书写中文网站或中文Web应用程序的时候,可以将代码清单6-1中的代码修改为代码清单6-2中所示代码。
代码清单6-2 将支架模板自动生成的代码进行汉化
@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>
<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>
<p>
<input type="submit" value="追加" />
</p>
</fieldset>
}
<div>
@Html.ActionLink("返回电影列表", "Index")
</div>
修改完毕后重新运行程序,然后访问“http://localhost:xx/Movies/Create”这个地址,浏览器中显示如图6-3所示。
图6-3 中文化后的追加电影信息画面
鼠标右击浏览器中显示的该页面,点击“显示源代码”,显示出来的源代码如代码清单6-3所示。(为了突出本节内容,只显示与本节中相关部分)。
代码清单6-3 追加电影信息画面在浏览器中的HTML代码
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>追加电影信息</title>
<link href="/Content/Site.css" rel="stylesheet" type="text/css" />
<script src="/Scripts/jquery- 1.4.4.min.js"
type="text/javascript"></script>
</head>
<body>
<h2>追加电影信息</h2>
<script src="/Scripts/jquery.validate.min.js"
type="text/javascript"></script>
<script src="/Scripts/jquery.validate.unobtrusive.min.js"
type="text/javascript"></script>
<form action="/Movies/Create" method="post">
<fieldset>
<legend>电影</legend>
<div class="editor-label">
标题
</div>
<div class="editor-field">
<input class="text-box single-line" id="Title" name="Title"
type="text" value="" />
<span class="field-validation-valid" data-valmsg-for="Title"
data-valmsg-replace="true"></span>
</div>
<div class="editor-label">
发行日期
</div>
<div class="editor-field">
<input class="text-box single-line" data-val="true"
data-val-required="The ReleaseDate field is required."
id="ReleaseDate" name="ReleaseDate" type="text" value="" />
<span class="field-validation-valid"
data-valmsg-for="ReleaseDate"
data-valmsg-replace="true">
</span>
</div>
<div class="editor-label">
种类
</div>
<div class="editor-field">
<input class="text-box single-line" id="Genre" name="Genre"
type="text" value="" />
<span class="field-validation-valid" data-valmsg-for="Genre"
data-valmsg-replace="true"/>
</div>
<div class="editor-label">
票价
</div>
<div class="editor-field">
<input class="text-box single-line" data-val="true"
data-val-number="The field Price must be a number."
data-val-required="The Price field is required." id="Price"
name="Price" type="text" value="" />
<span class="field-validation-valid" data-valmsg-for="Price"
data-valmsg-replace="true"></span>
</div>
<p>
<input type="submit" value="追加" />
</p>
</fieldset>
</form>
<div>
<a href="/Movies">返回电影列表</a>
</div>
<div id="footer">
</div>
</body>
</html>
从这段代码中可以看出,表单的action属性被设置为“/Movies/Create”,当点击追加按钮时会把表单中各文本框中的数据提交到服务器端进行保存。
6.2 处理HTTP-POST
到此为止,我们已经实现了显示追加数据所用表单的所需代码。我们的下一步是编写代码来进行表单提交到服务器后的处理。我们将要获取用户在数据库中输入的信息并且将它们作为一个新的Movie保存到数据库中。
为了实现这一处理,我们需要在MoviesController类中追加第二个Create方法。这个Create方法具有一个[HttpPost]属 性,它意味着我们将要用它来处理提交到“/Movies/Create”这个URL地址的请求。另外,所有提交到“/Movies/Create”这个 URL地址的非POST的请求(即GET请求)将被第一个Create方法进行处理,即简单地返回一个空的表单。
代码清单6-4中所示代码为MoviesController类中的两个Create方法的全部代码。
代码清单6-4 MoviesController类中的两个Create方法的全部代码
public ActionResult Create()
{
return View();
}
[HttpPost]
public ActionResult Create(Movie newMovie)
{
if (ModelState.IsValid)
{
db.Movies.Add(newMovie);
db.SaveChanges();
return RedirectToAction("Index");
}
else
return View(newMovie);
}
之前我们介绍了ASP.NET MVC可以自动地将一个URL地址中的查询字符串中的参数(例如:传递到“/HelloWorld/Welcome?name=Scott&numTimes=5”)作为一个方法的参数传递到方法中。同样地,除了传递查询字符串中的参数之外,ASP.NET MVC也可以用这种方法来传递提交后的表单参数。
提交后的表单参数可以作为一个独立的参数传递到一个方法中。例如,ASP.NET MVC framework可以将我们提交的表单中的控件值作为参数传递到具有HttpPost属性的Create方法中,如下所示。
[HttpPost]
public ActionResult Create(string title, DateTime releaseDate, string genre,
decimal price)
{
提交的表单值也可以被映射到一个复合的,具有属性的对象(譬如我们的Movie类),并且作为一个单一的参数传递到一个方法中。在代码清单6-4中我们使用的就是这个方法。请注意Create方法是怎样作为一个参数来接收Movie对象的。
[HttpPost]
public ActionResult Create(Movie newMovie)
{
if (ModelState.IsValid)
{
db.Movies.Add(newMovie);
db.SaveChanges();
return RedirectToAction("Index");
}
else
return View(newMovie);
}
ModelState.IsValid属性用来检查提交的表单中的数据是否能够被用来创建一个Movie对象。如果数据是有效的,我们的代码将把提交上来的这个Movie类追加在MoviesDBContext对象的实例中的Movies集合中。调用我们的MoviesDBContext对象实例的SaveChanges方法将把这个Movie对象保存在数据库中。保存数据完毕后,代码把画面重定向到MoviesController类的Index方法中,浏览器中将会打开电影清单显示画面,并且在电影清单中显示刚才追加的这条数据。
如果提交的值是无效的,将会返回到电影信息追加画面中,并且在表单的各输入控件中显示各自的提交的值。各输入控件的Html.ValidationMessageFor帮助器将会显示对应的出错信息。
6.3 追加一条电影信息
运行应用程序,在浏览器中输入“http://localhost:xx/Movies/Create”,在表单中输入一条电影信息,然后点击追加按钮,如图6-4所示。
图6-4 追加电影信息
点击追加按钮进行提交,表单中输入的这条电影信息将会保存到数据库中,保存后浏览器中将打开电影清单画面,并且将这条追加的电影显示在清单中,如图6-5所示。
图6-5 追加后电影将显示在电影清单中
你可能已经注意到了在这个电影清单画面中将刚才追加的电影票价显示成了10元,而不是用户输入的9.99元,这是因为当前该数据表中Decimal类型的默认精度只能识别与处理整数值,并且自动将小数部分四舍五入。关于如何解决这个问题,我们将在下一节中对模型进行一些调整的时候会同时进行介绍。
现在我们已经有了一个Web应用程序的雏形,我们可以在数据库中追加数据,显示数据。代码清单6-5是现在这个MoviesController类的完整代码。
代码清单6-5 MoviesController类的完整代码
using MvcMovie.Models;
using System.Linq;
using System;
using System.Web.Mvc;
namespace MvcMovie.Controllers
{
public class MoviesController : Controller
{
MovieDBContext db = new MovieDBContext();
public ActionResult Index()
{
var movies=from m in db.Movies
where m.ReleaseDate>new DateTime(1984,6,1)
select m;
return View(movies.ToList());
}
public ActionResult Create()
{
return View();
}
[HttpPost]
public ActionResult Create(Movie newMovie)
{
if (ModelState.IsValid)
{
db.Movies.Add(newMovie);
db.SaveChanges();
return RedirectToAction("Index");
}
else
return View(newMovie);
}
}
}
在下一节,我们将介绍如何为我们的模型添加附加的属性,如何在映射后的数据库中定制我们的票价列的精度。