本文参考:http://www.cnblogs.com/willick/p/3424188.html。

1、Model Binding是Http请求和Action方法之间的桥梁,是MVC框架根据Http请求创建.NET对象的过程。它根据Action方法中的Model对象的类型创建,NET对象,并将Http请求数据经过转换赋给该对象。

2、Model Binding是从路由引擎接收和处理Http请求后开始的。例如:

public static void RegisterRoutes(RouteCollection routes)
{ routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } );
}//1、当请求/Home/Index/1时,路由系统把最后一个片段1赋值给id变量。//2、Action Invoker通过路由信息得知当前请求需要Index这个Action来处理;//3、Action Invoker通过Model Binder(模型绑定器)来创建调用Action方法需要的数据对象;//4、最后Action Invoker将数据对象赋值给Index这个Action的参数,再调用这个Action完成Http请求。

3、Model Binder实现了下列接口:

namespace System.Web.Mvc
{ public interface IModelBinder { object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext); }
}

在MVC中可以有多个Model Binder,每个Binder都负责一种或多种类型的Model。当Action Invoker调用Action方法时,它先看这个Action方法需要的参数,然后为每个参数找到和参数类型对应的Model Binder,然后调用Model Binder的BindModel方法,BindModel方法再根据Action方法的参数名称从路由信息中获取参数值,最后把值提供给Action Invoker,由Action Invoker方法完成Action方法的调用。

4、Model Binder可以形象的理解为把数据绑定到一个Model的工具。当Action Invoker没有找到自定义的Model Binder时,就使用系统默认的DefaultModelBinder,它通过以下顺序查找要绑定到Model的值,一旦找到就停止查找:

  • Request.Form,HTML form 元素提供的值。
  • RouteData.Values,通过应用程序路由提供的值。
  • Request.QueryString,所请求 URL 的 query string 值。
  • Request.Files,客户端上传的文件

对于简单类型,DefaultModelBinder会通过System.ComponentModel命名空间下的TypeDescriptor类将其转换为和参数类型相同的类型。若转换失败则不会把值绑定到参数上。

    Tips:对于值类型,尽量使用可空类型或可选参数,以免报错。

5、对于复合类型(指不能被TypeConverter转换的类型),DefaultModelBinder类通过反射获取该类型所有的公开属性,然后依次进行绑定。

6、如果某个Action方法的参数的类型是某个对象的属性的类型,此时需要使用BindAttribute来告诉DefaultModelBinder只查找特定前缀的的名称:

public ActionResult DisplayAddress([Bind(Prefix="HomeAddress")]Address address)
{return View(address);
}

需要注意的是使用 Bind 特性指定了前缀后,需要提交的表单元素的 name 属性必须有该前缀才能被绑定。

Bind 特性还有两个属性,Exclude 和 Include。它们可以指定在 Mdoel 的属性中,Binder 不查找或只查找某个属性,即在查找时要么只包含这个属性要么不包含这个属性。

7、Model Binder 把请求提交的数据绑定到数组和集合模型上有非常好的支持。

8、当 action 方法定义了参数时,Model Binding 的过程是自动的。我们也可以通过在Action方法中调用UpdateModel方法来对Model Binding的过程进行手动控制。示例:

public ActionResult Address()
{IList<Address> addresses = new List<Address>();UpdateModel(addresses, new FormValueProvider(ControllerContext));return View(addresses);
}

示例指定只从Request.Form中查找数据。

9、FormValueProvider实现了IValueProvier接口,是ValueProvider的一种。RouteData.Values、Request.QueryString 和 Request.Files 的 Value Provider 分别是 RouteDataValueProviderQueryStringValueProviderHttpFileCollectionValueProvider

10、还有一种限制Model Binder数据来源的方法,示例:

//用 Action 方法的某个集合类型的参数来指定并存储从某一个来源获取的数据,这个集合类型(示例的 FormCollection) 也是 IValueProvider 接口的一个实现。public ActionResult Address(FormCollection formData)
{IList<Address> addresses = new List<Address>();UpdateModel(addresses, formData);return View(addresses);
}

11、有时候用户会提交一些 和 model 对象的属性不匹配的数据,如不合法的日期格式或给数值类型提供文本值,这时候绑定会出现错误,Model Binder 会用 InvalidOperationException 来表示。可以通过 Controller.ModelState 属性找到具体的错误信息,然后反馈给用户:

public ActionResult Address(FormCollection formData)
{IList<Address> addresses = new List<Address>();try {UpdateModel(addresses, formData);}catch (InvalidOperationException ex) {var allErrors = ModelState.Values.SelectMany(v => v.Errors);// do something with allErrors and provide feedback to user
    }return View(addresses);
}

12、可以用 ModelState.IsValid 属性来检查提交的数据是否合法。

13、自定义ValueProvider示例:

//1、实现IValueProvier接口
public class CountryValueProvider : IValueProvider
{public bool ContainsPrefix(string prefix){return prefix.ToLower().IndexOf("country") > -1;}public ValueProviderResult GetValue(string key) {if (ContainsPrefix(key))return new ValueProviderResult("China", "China", CultureInfo.InvariantCulture);elsereturn null;}
}//2、自定义ValueProviderFactory来实例化自定义的ValueProvider
public class CustomValueProviderFactory : ValueProviderFactory
{public override IValueProvider GetValueProvider(ControllerContext controllerContext) {return new CountryValueProvider();}
}//3、在Global类的Applcation_Start方法中进行注册
protected void Application_Start()
{AreaRegistration.RegisterAllAreas();//通过 ValueProviderFactories.Factories 静态集合的 Insert 方法注册了我们的 CustomValueProviderFactory 类。    //Insert 方法中的 0 参数保证 Binder 将首先使用自定义的类来提供值。    //如果我们想在其他 value provider 不能提供值的时候使用,那么我们可以使用 Add 方法:ValueProviderFactories.Factories.Add(new CustomValueProviderFactory());ValueProviderFactories.Factories.Insert(0, new CustomValueProviderFactory());
}

14、自定义Model Binder示例:

//1、实现IModelBinder接口
public class AddressBinder : IModelBinder
{public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) {Address model = (Address)bindingContext.Model ?? new Address();model.City = GetValue(bindingContext, "City");model.Country = GetValue(bindingContext, "Country");return model;}private string GetValue(ModelBindingContext context, string name) {name = (context.ModelName == "" ? "" : context.ModelName + ".") + name;ValueProviderResult result = context.ValueProvider.GetValue(name);if (result == null || result.AttemptedValue == "") return "<Not Specified>";else return (string)result.AttemptedValue;}
}//2、注册
protected void Application_Start()
{AreaRegistration.RegisterAllAreas();ModelBinders.Binders.Add(typeof(Address), new AddressBinder());
}

转载于:https://www.cnblogs.com/wangwust/p/6392587.html

【ASP.NET MVC 学习笔记】- 16 Model Binding(模型绑定)相关推荐

  1. 【ASP.NET MVC 学习笔记】- 07 使用 Entity Framework

    本文参考:http://www.cnblogs.com/willick/p/3304534.html 1.ORM(Object Relation Mapping)工具,是为了解决"关系数据库 ...

  2. 【ASP.NET MVC 学习笔记】- 10 Controller和Action(1)

    本文参考:http://www.cnblogs.com/willick/p/3331521.html 1.继承IController接口,示例代码将当前请求的Controller和Action打印到浏 ...

  3. 【ASP.NET MVC 学习笔记】- 09 Area的使用

    本文参考:http://www.cnblogs.com/willick/p/3331519.html 1.ASP.NET MVC允许使用 Area(区域)来组织Web应用程序,这对于大的工程非常有用, ...

  4. 【ASP.NET MVC 学习笔记】- 06 在MVC中使用Ninject

    本文参考:http://www.cnblogs.com/willick/p/3299077.html 1.在ASP.NET MVC中一个客户端请求是在特定的Controller的Action中处理的. ...

  5. 【OSATE学习笔记】Model Analyses 模型分析方法

    介绍 本文介绍aadl模型实例化后,进行Flow Latency Analysis.Bus Load Analysis两种分析方法 本文相关范例下载地址: osate官方样例 examples: Gi ...

  6. ASP.NET MVC学习之路由篇(2)

    ASP.NET MVC学习之路由篇(2) 原文:ASP.NET MVC学习之路由篇(2) 继ASP.NET MVC学习之路由篇(1)后继续学习. 7.解决与物理路径的冲突 当发送一个请求至ASP.NE ...

  7. ASP.NET MVC学习之控制器篇

    一.前言 许久之后终于可以继续我的ASP.NET MVC连载了,之前我们全面的讲述了路由相关的知识,下面我们将开始控制器和动作的讲解. ASP.NET MVC学习之路由篇幅(1) ASP.NET MV ...

  8. .NET MVC 学习笔记(一)— 新建MVC工程

    一..NET MVC 学习笔记(一)-- 新建MVC工程 接触MVC有段时间了,一直想找机会整理一下,可是限于文笔太差,所以一直迟迟羞于下手,想到最近做过的MVC项目也有一些了,花点时间整理一下方便以 ...

  9. (转)ASP.NET MVC 学习第一天

    天道酬勤0322 博客园 | 首页 | 发新随笔 | 发新文章 | 联系 | 订阅  | 管理 随笔:10 文章:0 评论:9 引用:0 ASP.NET MVC 学习第一天 今天开始第一天学习asp. ...

最新文章

  1. Sping中利用HandlerExceptionResolver实现全局异常捕获
  2. Failed to start mongod.service: Unit mongod.service not found
  3. 如何使用spring配合mybatis配置多个数据源并应用?
  4. java异常了还会往下走吗_异常一个问题,请帮下忙:处理异常后,程序会继续往下运行吗...
  5. 前端必须懂的计算机网络知识—(跨域、代理、本地存储)(掘金)
  6. OCS 2007 R2搭建后端SQL 2005企业版池
  7. NuCypher 已将共享策略访问周期持续时间从 24 小时延长至 7 天
  8. 总结一下目标检测与跟踪
  9. python中的jieba分词使用手册_Python jieba结巴分词原理及用法解析
  10. stm32驱动ssd1306配置_自制FOC控制驱动器
  11. linux查看db2表空间大小,db2怎么列出当前数据库下全部表占用空间的大小
  12. Cocos2dx-lua组件tableView的简单用法
  13. 本科毕业设计——基于C++的棋类游戏自动生成工具的设计与实现
  14. 计算机应用专业,报软考应该选什么?
  15. 高效能人士的七个习惯(零)前言
  16. 几何分布的众数为什么是1
  17. AUTOSAR架构软件结构简介
  18. HUAWEI 机试题:工厂流水线调度
  19. 计算机职场礼仪与技巧论文,职场礼仪论文1500字.doc
  20. 资料:SAP所有模块用户出口(User Exits)

热门文章

  1. 创建 OVS 外部网络 ext_net - 每天5分钟玩转 OpenStack(144)
  2. 编写高质量代码改善C#程序的157个建议——建议87:区分WPF和WinForm的线程模型...
  3. Tomcat绿色版启动startup.bat一闪问题的解决方法!
  4. 用 GDI 操作 EMF 文件[8]: 绘制图元文件时改变画笔与画刷
  5. JavaEE配置工具
  6. selenium + python 登录页面,输入账号、密码,元素定位问题
  7. VC++编译zlib
  8. ExtJS4.x动态加载js文件
  9. jquery 表格(鼠标悬停改变改变行背景+隔行换色)
  10. 今日学习心得——装饰模式