西北狼

-- 学而时习之,不亦乐乎!
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

MVC学习之实现HTTP-GET的Create Action方法

Posted on 2009-05-14 13:21  西北老狼  阅读(831)  评论(0编辑  收藏  举报
实现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对象的详细信息: