实现HTTP-POST的Edit Action方法

 
现在,我们已经实现了支持HTTP-GET的Edit action方法。当用户请求/Dinners/Edit/2 地址时,接收一个HTML页面。点击Save保存按钮,将触发表单提交到/Dinners/Edit/2 网址,并通过HTTP POST提交<input> 表单中的值。下面,我们开始实现HTTP POST的Edit action 方法 – 负责处理保存操作。
 
通过添加一个重载的Edit action 方法到DinnersController类中,并设置AcceptVerbs属性,表示该方法负责处理HTTP POST动作。
        //
        // POST: /Dinners/Edit/2
        [AcceptVerbs(HttpVerbs.Post)]
        publicActionResult Edit(int id,FormCollection formValues) {
 
        }
当对重载的action 方法添加[AcceptVerbs] 属性后,ASP.NET MVC根据进来的HTTP动作,自动分发请求给合适的action方法。HTTP POST 请求/Dinners/Edit/[id] 将有上述Edit方法负责处理,然而所有其他的HTTP 请求/Dinners/Edit/[id] 将有之前定义的Edit方法负责(该方法没有[AcceptVerbs]属性)。
 
获取表单提交的值
在HTTP POST的Edit方法中,有很多方法可以获取表单参数值。一个简单的办法是使用Controller基类的Request属性来访问form集合,并直接获取提交的参数值:
        //
        // POST: /Dinners/Edit/2
        [AcceptVerbs(HttpVerbs.Post)]
        publicActionResult Edit(int id,FormCollection formValues)
        {
            // Retrieve existing dinner
            Dinner dinner = dinnerRepository.GetDinner(id);
 
            // Update dinner with form posted values
            dinner.Title = Request.Form["Title"];
            dinner.Description = Request.Form["Description"];
            dinner.EventDate = DateTime.Parse(Request.Form["EventDate"]);
            dinner.Address = Request.Form["Address"];
            dinner.Country = Request.Form["Country"];
            dinner.ContactPhone = Request.Form["ContactPhone"];
 
            // Persist changes back to database
            dinnerRepository.Save();
 
            // Perform HTTP redirect to details page for the saved Dinner
            return RedirectToAction("Details", new { id = dinner.DinnerID });
        }
 
上述方法有一点繁琐,特别是增加异常处理逻辑之后。
一个更好的方法是使用Controller 基类的内置方法UpdateModel()。该方法支持使用传入的表单参数更新对象的属性,它使用反射机制来解析对象的属性名称,接着基于客户端传入的参数值自动赋值给对象相关属性。
 
下面,我们使用UpdateModel() 方法来实现之前的HTTP-POST Edit Action 方法:
        //
        // POST: /Dinners/Edit/2
        [AcceptVerbs(HttpVerbs.Post)]
        publicActionResult Edit(int id,FormCollection formValues)
        {
            // Retrieve existing dinner
            Dinner dinner = dinnerRepository.GetDinner(id);
 
            UpdateModel(dinner);
 
            // Persist changes back to database
            dinnerRepository.Save();
 
            // Perform HTTP redirect to details page for the saved Dinner
            return RedirectToAction("Details", new { id = dinner.DinnerID });
        }
 
再次方法/Dinners/Edit/2 网址,并更改Dinner的标题和事件日期:
 

 
点击Save保存按钮,执行表单提交,触发Edit方法的调用,并将更新的值持久化到数据库。接着,重定向到详细页面 – Details视图(显示最新保存的数据)。
 
 
处理编辑异常
当前HTTP-POST实现方法工作正常 – 当然也会出现异常。当用户在编辑表单时犯错误了,我们需要确保表单显示错误信息,指导用户去纠正。这包括用户提交了错误的数据(如错误的日期格式),或者存在业务规则冲突等等。当发生错误是,表单需要保持用户初始录入的数据,这样他们不必重复录入一遍。这个过程需要重复多次,直到最终成功提交表单。
 
ASP.NET MVC 包括一些友好的内置功能,使异常处理和重新显示表单更容易。为了演示这些功能,下面我们再次更新Edit Action 方法,代码如下:
        //
        // POST: /Dinners/Edit/2
        [AcceptVerbs(HttpVerbs.Post)]
        publicActionResult Edit(int id,FormCollection formValues)
        {
            Dinner dinner = dinnerRepository.GetDinner(id);
 
            try
            {
                UpdateModel(dinner);
                dinnerRepository.Save();
                return RedirectToAction("Details", new { id = dinner.DinnerID });
            }
            catch
            {
                foreach (var issue in dinner.GetRuleViolations())
                {
                    ModelState.AddModelError(issue.PropertyName, issue.ErrorMessage);
                }
                return View(dinner);
            }
        }
 
上述代码与之前的实现基本一致,除了增加了一个try/catch 异常捕获代码块。如果调用UpdateModel() 方法出现异常,或者保存DinnerRepository 时出现异常(如果我们试图保存一个无效的对象-规则冲突,将抛出异常),异常捕获代码块将触发执行。在catch代码块中,首先遍历Dinner对象中所有规则冲突,并添加到ModelState对象中,接着重新显示视图。
 
下面为了模拟异常信息,重新运行应用程序,编辑Dinner,并将Title清空,事件日期EventDate设置为ENTLIB,电话格式等等,然后点击Save保存按钮,现在HTTP POST触发Edit方法,但不能成功保存Dinner信息(因为有异常么),并重新显示表单:
 

 
现在,应用程序有更好的异常处理机制。有无效输入的文本框通过红色*进行提示,并且错误信息也显示在界面上。表单同时也保留了用户最初录入的信息 – 这样他们不必重复录入。所有这些是如何实现的呢?这是因为我们使用了一些内置的ASP.NET MVC功能,使输入验证和异常处理更加容易。
来自西北的狼!
posted @ 2012-02-24 12:08  haiziguo  阅读(801)  评论(0编辑  收藏  举报