一步一步学习ASP.NET MVC 1.0创建NerdDinner 范例程序,Part 13


一步一步学习ASP.NET MVC 1.0创建NerdDinner 范例程序,Part 13
 
本文根据《Professional ASP.NET MVC 1.0》中微软牛人Scott Guthrie 提供免费下载的第一章,一步一步演示如何通过ASP.NET MVC 1.0 正式版创建NerdDinner 范例程序。对了解如何使用最新的ASP.NET MVC 1.0框架创建Web Application 非常有帮助。本文由http://forum.entlib.com 开源论坛小组提供。关于本文的一些资源,请参考文章最后的链接。
 
前面系列文章:
 
本文继续学习之旅,一步一步通过ASP.NET MVC 1.0 实现NerdDinner 范例程序。
 
实现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)]
        public ActionResult 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)]
        public ActionResult 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)]
        public ActionResult 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)]
        public ActionResult 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功能,使输入验证和异常处理更加容易。
 
今天就到这里了,明天继续翻译ASP.NET MVC eBook – 开发NerdDinner 范例程序向导。欢迎访问http://blog.EntLib.com 博客平台获取更多的MVC学习资料。
 

 

发表 @ 2009年4月2日 22:38

打 印

评论

# re: 一步一步学习ASP.NET MVC 1.0创建NerdDinner 范例程序,Part 13

Left by silenus-G at 2009/4/24 16:53
Gravatar
支持支持!!

# re: 一步一步学习ASP.NET MVC 1.0创建NerdDinner 范例程序,Part 13

Left by cg516 at 2009/6/5 10:27
Gravatar
nnd,我把电话和国家那个认证去了。每次都说我出错。

# re: 一步一步学习ASP.NET MVC 1.0创建NerdDinner 范例程序,Part 13

Left by wys at 2009/7/2 15:55
Gravatar
我想问下对于电话号码,中国的电话号码是什么要求啊,是不是8个数字,但是我开始填88888888就可以,当我编辑的时候填上88888887就不行了,不知道什么原因。

# re: 一步一步学习ASP.NET MVC 1.0创建NerdDinner 范例程序,Part 13

Left by hh at 2009/7/3 11:12
Gravatar
为什么我把Title清空后,点save按钮就会报错
未将对象引用设置到对象的实例
<p>
行 18: <label for="Title">标题:</label>
行 19: <%= Html.TextBox("Title", Model.Title) %>
行 20: <%= Html.ValidationMessage("Title", "*") %>
行 21: </p>

# re: 一步一步学习ASP.NET MVC 1.0创建NerdDinner 范例程序,Part 13

Left by hh at 2009/7/3 14:01
Gravatar
在DinnersController中
// POST: /Dinners/Edit/2
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(int id, FormCollection formValues)
{
.......
catch
{
foreach (var issue in dinner.GetRuleViolations())
{
ModelState.AddModelError(issue.PropertyName, issue.ErrorMessage);
ModelState.SetModelValue(issue.PropertyName,new ValueProviderResult(null,null,null));
}
return View(dinner);
}
就好了,没人遇到吗?我查了一下说是"The solution to this problem could be very easy: just add check for null into System.Web.Mvc.HtmlHelper.GetModelStateValue method. ",楼主能解释一下吗?

# re: 一步一步学习ASP.NET MVC 1.0创建NerdDinner 范例程序,Part 13

Left by yupinghuashi at 2009/7/19 3:31
Gravatar
en 看来还是美国电话 格式嘛

# re: 一步一步学习ASP.NET MVC 1.0创建NerdDinner 范例程序,Part 13

Left by yupinghuashi at 2009/7/19 3:39
Gravatar
看来 做教研要做得 麻烦得多啊 是不是大家试试重写下了
主要这个教研逻辑有问题啊

try
{
UpdateModel(dinner);
dinnerRepository.Save();
return RedirectToAction("Details", new { id = dinner.DinnerID });
}
catch
{

// 数据库的问题 无法体现了也无法 得到正确的报错
//无法修改 报错语言啊 怎么软语言友好点了 而其还是中文的了
//更可怕的是 网页可能会down掉
foreach (var issue in dinner.GetRuleViolations())
{
ModelState.AddModelError(issue.PropertyName, issue.ErrorMessage);
}
return View(dinner);
}

# re: 一步一步学习ASP.NET MVC 1.0创建NerdDinner 范例程序,Part 13

Left by yupinghuashi at 2009/7/19 3:42
Gravatar
我想这个扩展出来的 校验 中没有用到适合中国的正则表达

# re: 一步一步学习ASP.NET MVC 1.0创建NerdDinner 范例程序,Part 13

Left by yupinghuashi at 2009/7/19 3:42
Gravatar
客服要杀了我的啊

您的评论:



 (不显示)


 
 
 
Please add 5 and 3 and type the answer here:
    
 

评论预览窗口:

 
«九月»
2930311234
567891011
12131415161718
19202122232425
262728293012
3456789