ASP.NET MVC模型绑定的6个建议

发表于2011-08-03 10:25| 来源博客园| 31 条评论| 作者冠军
摘要:ASP.NET MVC中的Model Binding使用起来非常简单,本文总结了关于在MVC项目中更好使用Model Binding的一些建议。供大家学习、参考。

ASP.NET MVC中的Model Binding使用起来非常简单。你的Action方法需要数据,在传入的HTTP请求中携带着你需要的数据,数据可以在请求的表单数据中,还可能在你的URL地址本身中。通过DefaultModelBinder,可以神奇地将表单中的数据和路由中的数据转换到对象中。Model Binder使得你的控制器代码可以干净地从请求以及关联的环境中分离出来。

这里有一些关于在MVC项目中更好使用Model Binding的建议。

Tip#1:最好使用Model Binding而不是Request.Form

如果你的Action像下面这样:

[AcceptVerbs(HttpVerbs.Post)]   

public ActionResult Create()   

{   

    Recipe recipe = new Recipe();   

    recipe.Name = Request.Form["Name"];   

    // ...   

    return View();   

}   

就不对了。这些属性使得你的Action很难读而且更难以测试,Model Binder可以帮你从Request和HttpContext中摆脱出来。比如,你可以使用FormCollection类型的参数来代替上面的代码:

public ActionResult Create(FormCollection values)   

{   

    Recipe recipe = new Recipe();   

    recipe.Name = values["Name"];         

    // ...   

    return View();   

}   

使用FormCollection你可以不必再深入到Request对象,这样,有时候你就可以使用低层次的控制了。但是,如果你的数据来自Request.Form,或者URL请求参数,你可以通过Model Binding来完成它的魔术。

[AcceptVerbs(HttpVerbs.Post)]   

public ActionResult Create(Recipe newRecipe)   

{               

    // ...   

    return View();   

} 

在这个例子中,Model Binder将会帮你创建newRecipe对象,并且使用从Request中获得获得的数据来填充它,真的是魔术。有许多的途径允许你定制绑定的处理过程,使用白名单,黑名单,前缀,以及接口,更多的控制还允许你通过UpdateModel和TryUpdateModel方法进行,只是要注意无意的绑定。看一看Justin Etheredge的文章Think Before You Bind.

Tip#2定制Model Binder

在MVC中,Model Binding也是一个扩展点。如果默认的绑定不合适的话,你可以提供一个自定义的Model Binder,实现自定义的Model Binder你需要实现接口IModelBinder,这是仅有的一个方法,有多难吗?

public interface IModelBinder   

{   

    object BindModel(ControllerContext controllerContext,   

                      ModelBindingContext bindingContext);   

}   

一旦你进入Model Binding,实际上,你将会发现这个简单的IModelBinder接口并没有完全描述在框架中的默认契约和负作用。如果你退回一步看一看,就会发现Model Binder,ModelState以及HtmlHelper。

Scott Hanselman在他的 “Splitting DateTime – Unit Testing ASP.NET MVC Custom Model Binders”中给出了一个并不是演示版的Model Binder,一个我需要提出来的细节是Scott的DateTime分离器仍然没有通过Request.Form来绑定,在GetA<T> 方法中,你将会看到Scott使用了上下文对象的ValueProvider属性来获得数据,ValueProvier表示混合了表单数据,路由数据,以及请求参数数据的数据。Scott的例子非常棒,但是,少了一个细节:绑定中的错误。

如果默认的模型绑定器在将数据绑定到你的对象上时出现了问题,它会将错误信息和错误的数据压入到ModelState中,你可以检查ModelState.IsValid来检查绑定中的问题,使用ModelState.AddModelError 方法可以注入你自己的错误信息。

如果你看看Scott文章的回应,你会看到Sebastien Crocquesel’s 对这个问题的补丁。如果转换失败,Sebastien的代码将会使用ModelState.AddModelError方法来表示错误。Controller和View都会使用ModelState来检查绑定的问题。Controller需要检查ModelState,以便在将数据保存到数据库之前检查错误,而View需要通过ModelState来为用户提供验证的回应。需要注意的一点是HtmlHelper,你需要同时提供一个值,通过ModelState.SetModelValue,并且提供错误信息,通过AddModelError,否则你将会得到一个运行时的空引用异常,下面的代码演示了这个问题。

[AcceptVerbs(HttpVerbs.Post)]   

public ActionResult Create(FormCollection Form)   

{   

    // this is the wrong approach ...   

    )   

        ModelState.AddModelError("Name", "Name is required");   

    return View();   

}  

上面的代码创建了一个模型的错误信息,但是没有提供值。也有其他的问题,但是,如果你像下面一场呈现视图,那么,就会得到一个异常。

<%= Html.TextBox("Name", Model.Name) %>

纵然你为 Model.Name 提供了一个值,HtmlHelper 也会发现错误,然后显示试图的值。如果你没有提供值,就会看到一个空引用异常。

Tip#3通过继承来自定义Model Binding

如果你决定实现一个自定义的Model Binder,你可能希望通过从DefaultModelBinder继承来减少部分工作量,其实,最终你会发现不能通过继承DefaultModelBinder 来达到你的目的。例如,假如你希望通过自定义的 ModelBinder来创建某些对象,DefaultModelBinder将会使用Activator.CreateInstance和Model的默认构造函数来创建对象,如果你的模型没有提供默认的构造函数,你可以重写CreateModel方法来解决这个问题。

Jimmy有一篇关于使用DefaultModelBinder的派生类的帖子“A Better Model Binder”.

Tip#4使用注解来完成验证

Brad Wilson在他的文章DataAnnotations and ASP.NET MVC中,完美地演示了一切。

我建议你仔细读一下Brad Wilson的文章,如果你想快一点,这里总结了一下。

.NET 3.5 SP1带来了System.ComponentModel.DataAnnotations程序集,通过数据的注解和DataAnnotationModelBinder,你可以处理大部分的服务器端验证问题,只需要简单地标注你的模型

public class Recipe   

{   

    [Required(ErrorMessage="We need a name for this dish.")]   

    [RegularExpression("^Bacon")]    

    public string Name { get; set; }   

    // ...   

}   

Tip#5绑定和验证是两个步骤

绑定是从环境中获得数据,然后赋予模型对象的过程,验证是检查模型对象的数据,确认符合我们的期望。这是完全不同的操作,但是模型绑定模糊了他们的区别。如果你希望在Model Binder中一起完成这两步工作,是可以的,这需要准确地知道DataAnnotationsModelBinder做了什么,你可以看这几个例子。实际上,经常被忽略的一点是DefaultModelBinder如何分离绑定和验证步骤。如果只是简单属性的验证,所有你要做的就是重写DefaultModelBinder的OnProperValidating方法。

下面的几篇文章可以参考一下:

Tip#6关于绑定的内容

前面我说过:Model Binder可以帮你从Request和HttpContext中摆脱出来。从更加广泛的角度来说,并没有限制数据的来源,请求上下文中包含丰富的客户端信息。Scott Hanselman的另外一篇文章演示了将用户的标识绑定到模型上。

综上所述

Model Binding是美妙的魔术,所以,尽可能使用内置的奇妙功能。

文章出自:博客园

英文出自:6 Tips for ASP.NET MVC Model Binding

ASP.NET MVC模型绑定的6个建议(转载)的更多相关文章

  1. ASP.NET没有魔法——ASP.NET MVC 模型绑定

    在My Blog中已经有了文章管理功能,可以发布和修改文章,但是对于文章内容来说,这里缺少最重要的排版功能,如果没有排版的博客很大程度上是无法阅读的,由于文章是通过浏览器查看的,所以文章的排版其实与网 ...

  2. ASP.NET没有魔法——ASP.NET MVC 模型绑定解析(下篇)

    上一篇<ASP.NET没有魔法——ASP.NET MVC 模型绑定解析(上篇)>文章介绍了ASP.NET MVC模型绑定的相关组件和概念,本章将介绍Controller在执行时是如何通过这 ...

  3. asp.net Mvc 模型绑定项目过多会导致页面运行时间卡

    asp.net Mvc 模型绑定项目过多会导致页面运行时间卡的问题. 解决方式就是采用ModelView方式进行精简,已减少模型绑定及验证的时间.

  4. [转] ASP.NET MVC 模型绑定的功能和问题

    摘要:本文将与你深入探究 ASP.NET MVC 模型绑定子系统的核心部分,展示模型绑定框架的每一层并提供扩展模型绑定逻辑以满足应用程序需求的各种方法. 同时,你还会看到一些经常被忽视的模型绑定技术, ...

  5. ASP.NET MVC——模型绑定

    这篇文章我们来讲讲模型绑定(Model Binding),其实在初步了解ASP.NET MVC之后,大家可能都会产生一个疑问,为什么URL片段最后会转换为例如int型或者其他类型的参数呢?这里就不得不 ...

  6. ASP.NET没有魔法——ASP.NET MVC 模型绑定解析(上篇)

    前面文章介绍了ASP.NET MVC中的模型绑定和验证功能,本着ASP.NET MVC没有魔法的精神,本章内容将从代码的角度对ASP.NET MVC如何完成模型的绑定和验证进行分析,已了解其原理. 本 ...

  7. ASP.NET MVC模型绑定1

    一.模型绑定原理 模型绑定是指为Controller的Action方法的参数提供值的过程,例如我有一个名为Blog的实体类(准确的说是ViewModel),它有一个名为Title的属性,如果我在VIE ...

  8. ASP.NET MVC 模型绑定

    模型绑定指的是MVC从浏览器发送的HTTP请求中为我们创建.NET对象,在HTTP请求和C#间起着桥梁的作用.模型绑定的一个最简单的例子是带参数的控制器action方法,比如我们注册这样的路径映射: ...

  9. 禁止ASP.NET MVC模型绑定时将空字符串绑定为null

    为model添加[DisplayFormat(ConvertEmptyStringToNull = false)] [Display(ResourceType = typeof(AppStrings) ...

随机推荐

  1. URL编码原理解释

    当你在浏览器中输入一个URL时,浏览器会将你输入到地址栏的非数字字母转化为URI编码. 那么,它是按照什么样的规则来转换的呢 是这样的,URI编码就是一个字符的ASCII码,它的ACSII码的十六进制 ...

  2. Delphi- 操作EXCEL

    因工作需要,需要到操作EXCEL,先了解一下怎么读取EXCEL这个,做了一个DEMO,备注在这里 一.读取EXCEL unit Unit1; interface uses Windows, Messa ...

  3. 最牛X的编码套路

    最近,我大量阅读了Steve Yegge的文章.其中有一篇叫"Practicing Programming"(练习编程),写成于2005年,读后令我惊讶不已: 与你所相信的恰恰相反 ...

  4. Cocos2d-x——CocosBuilder官方帮助文档翻译1 使用自定义类

    原创:请注明转载! 在Cocos2d-x中使用CocosBuilder 使用自定义类 CocosBuilder的使用方法是通过自定义类.在CocosBuilder中选中一个对象并在属性栏中输入自定义类 ...

  5. How to add “Maven Managed Dependencies” library in build path eclipse

    If you have m2e installed and the project already is a maven project but the maven dependencies are ...

  6. Oracle DataGuard数据备份方案详解

    Oracle DataGuard是一种数据库级别的HA方案,最主要功能是冗灾.数据保护.故障恢复等. 在生产数据库的"事务一致性"时,使用生产库的物理全备份(或物理COPY)创建备 ...

  7. SAP增强总结-第二代增强(SMOD、CMOD)【转载】

    第二代增强比第二代增强安全性提高了很多,第一代增强毕竟是在原标准程序中修改,大部分传递参数都可以直接使用,第二代增强做了一些封装,对用户可以修改的参数做了限制. 1.增强点查找方法 首先根据事物码找到 ...

  8. 最全面的Android Intent机制讲解

    对于大型软件开发经验较少的程序员来说,这可能是一个不太容易理解的抽象概念,因为它与我们平常使用的简单函数调用,或者通过库调用接口的方式不太一样.在 Intent 的使用中你看不到直接的函数调用,相对函 ...

  9. Web应用Word生成

    前段时间接到一个Web应用自己主动生成Word的需求,现整理了下一些关键步骤拿来分享一下. 思路:(注:这里仅仅针对WORD2003版本号.其他版本号大同小异.) 由于WORD文件内部的数据及格式等是 ...

  10. 【机器学习算法-python实现】svm支持向量机(1)—理论知识介绍

    (转载请注明出处:http://blog.csdn.net/buptgshengod) 1.背景      强烈推荐阅读(http://www.cnblogs.com/jerrylead/archiv ...