实现HTTP-GET的Create Action方法
前面我们完成了实现DinnersController类的Edit方法,接下来实现Create方法 – 允许用户添加新的Dinners记录。
下面开始实现Create Action方法的HTTP GET行为。在用户访问/Dinners/Create 地址时,将调用该方法,实现代码如下:
//
// GET: /Dinners/Create
public ActionResult Create()
{
Dinner dinner = new Dinner()
{
EventDate = DateTime.Now.AddDays(7)
};
return View(dinner);
}
上述代码创建一个Dinner对象,并对EventDate属性赋值DateTime.Now.AddDays(7)。接着基于新的Dinner对象呈现视图。因为我们没有显式传入名称给View() 辅助方法,因此它将基于惯例和默认路径解析视图模板:/Views/Dinners/Create.aspx。
下面创建视图模板。右键在Create Action方法内点击,并选择Add View菜单项。在Add View对话框表示将传入Dinner对象给视图模板,并选择Create模板。如下图所示:
当点击Add按钮,Visual Studio自动在\Views\Dinners 目录下创建Create.aspx视图文件。下面对默认创建的Create.aspx文件进行修改,修改之后的代码如下:
<asp:Content ID="Title" ContentPlaceHolderID="TitleContent" runat="server">
招待一个宴会
</asp:Content>
<asp:Content ID="Main" ContentPlaceHolderID="MainContent" runat="server">
<h2>招待一个宴会</h2>
<%= Html.ValidationSummary("Create was unsuccessful. Please correct the errors and try again.") %>
<% using (Html.BeginForm()) {%>
<fieldset>
<p>
<label for="Title">标题:</label>
<%= Html.TextBox("Title") %>
<%= Html.ValidationMessage("Title", "*") %>
</p>
<p>
<label for="EventDate">事件日期:</label>
<%= Html.TextBox("EventDate") %>
<%= Html.ValidationMessage("EventDate", "*") %>
</p>
<p>
<label for="Description">描述:</label>
<%= Html.TextBox("Description") %>
<%= Html.ValidationMessage("Description", "*") %>
</p>
<p>
<label for="HostedBy">主持人:</label>
<%= Html.TextBox("HostedBy") %>
<%= Html.ValidationMessage("HostedBy", "*") %>
</p>
<p>
<label for="ContactPhone">联系电话:</label>
<%= Html.TextBox("ContactPhone") %>
<%= Html.ValidationMessage("ContactPhone", "*") %>
</p>
<p>
<label for="Address">地址:</label>
<%= Html.TextBox("Address") %>
<%= Html.ValidationMessage("Address", "*") %>
</p>
<p>
<label for="Country">国家:</label>
<%= Html.TextBox("Country") %>
<%= Html.ValidationMessage("Country", "*") %>
</p>
<p>
<label for="Latitude">纬度:</label>
<%= Html.TextBox("Latitude") %>
<%= Html.ValidationMessage("Latitude", "*") %>
</p>
<p>
<label for="Longitude">经度:</label>
<%= Html.TextBox("Longitude") %>
<%= Html.ValidationMessage("Longitude", "*") %>
</p>
<p>
<input type="submit" value="创建" />
</p>
</fieldset>
<% } %>
<div>
<%=Html.ActionLink("返回列表", "Index") %>
</div>
</asp:Content>
现在,我们运行NerdDinner应用程序,并在浏览器中访问/Dinners/Create 网址,将根据Create Action方法的实现,呈现如下界面:
实现HTTP-POST的Create Action 方法
我们已经实现了Create Action方法的HTTP-GET版本。当用户点击Create创建按钮时,将执行表单提交到/Dinners/Create 地址,并使用HTTP POST动作提交HTML 表单参数。
现在开始实现HTTP POST动作的Create Action 方法。添加一个重载的Create action方法到DinnersController类,并设置AcceptVerbs属性,表示该方法负责处理HTTP POST的请求:
//
// POST: /Dinners/Create
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create() {
}
在HTTP-POST的Create方法中,有很多办法可以访问表单提交过来的参数值。
一个方法是创建新的Dinner对象,并使用UpdateModel() 辅助方法(就像Edit方法一样),将表单传递过来的值赋给Dinner对象。接着,添加Dinner对象到DinnerRepository,并持久化到数据库,并重定向到Details action方法,并显示新创建的Dinner对象:
//
// POST: /Dinners/Create
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create()
{
Dinner dinner = new Dinner();
try
{
UpdateModel(dinner);
dinnerRepository.Add(dinner);
dinnerRepository.Save();
return RedirectToAction("Details", new { id = dinner.DinnerID });
}
catch
{
ModelState.AddRuleViolations(dinner.GetRuleViolations());
return View(dinner);
}
}
另外一个方法是Create() action方法接收一个Dinner对象作为方法参数。接着ASP.NET MVC 自动实例化一个新的Dinner对象,并使用表单输入的参数赋值给Dinner对象的属性,然后传递给action方法,代码如下:
//
// POST: /Dinners/Create
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(Dinner dinner)
{
if (ModelState.IsValid)
{
try
{
dinnerRepository.Add(dinner);
dinnerRepository.Save();
return RedirectToAction("Details", new { id = dinner.DinnerID });
}
catch
{
ModelState.AddRuleViolations(dinner.GetRuleViolations());
}
}
return View(dinner);
}
上述方法通过检查ModelState.IsValid属性,来判断Dinner 对象是否成功通过表单提交过来的参数值进行赋值了。如果存在输入无效的数据,将返回False(如传入”EntLib” 给EventDate属性)。如果存在任何问题,action方法将重新显示表单。
如果输入的参数是有效的,action方法将试图添加和保存新的Dinner对象到DinnerRepository。代码块在try/catch块中,如果有任何业务规则冲突,将重新显示表单(这将导致dinnerRepository.Save()方法抛出异常)。
为了测试错误处理机制,我们请求/Dinners/Create URL地址,并填写了Dinner详细信息。不正确的输入将导致新建表单重新显示,并突出显示错误信息,如下图所示:
上述所有的验证和业务规则定义在Model类中,并没有嵌入在UI或者Controller类中。这意味着今后当我们需要更新验证或业务规则时,只需要在一个地方更新就可以了,并应用到整个应用程序中,而不必更新Edit或Create action方法。
当我们修改无效的输入后,再次点击创建Create按钮,DinnerRepository的Save操作将会成功,一个新的Dinner对象将添加到数据库。接着,重定向到/Dinners/Details/[id] 地址 – 并显示新创建的Dinner对象的详细信息:
来自西北的狼!