值提供器 AND 模型绑定器
本章介绍了值提供器的作用,ASP MVC自带的5中值提供器.以及模型绑定器的作用,自定义模型绑定器并使用自定义的模型绑定器(类型上加上[ModelBinder(typeof(xx))]或者在全局模型绑定器中注册)。
补充:全局模型绑定器中注册自定义模型绑定器
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
ModelBinders.Binders.Add(typeof(Point), new PointModelBinder());
}
值提供器
ASP .NET MVC 框架自带的若干值提供器可以提供以下数据源中的数据:
● 子操作(RenderAction)的显式值
● 表单值
● 来自 XMLHttpRequest 的 JSON 数据
● 路由值
● 查询字符串值
● 上传的文件
值提供器来自值提供器工厂,并且系统按照值提供器的注册顺序来从中搜寻数据(上面
的列表使用的是默认顺序,自顶而下)。开发人员可以编写自己的值提供器工厂和值提供器,
并且还可以将它们插入到包含在 ValueProviderFactories.Factories 中的工厂列表中。当在模
型绑定期间需要使用额外的数据源时,开发人员通常选择编写自己的值提供器工厂和值提
供器。
除了 ASP .NET MVC 本身包含的值提供器工厂以外,开发团队也在 ASP.NET MVC 3
Futures 包中包含了一些提供器工厂和值提供器,可从 http://aspnet.codeplex.com/releases/view/
58781 上下载,或者安装 NuGet 包 Mvc3Futures。具体包括以下提供器:
● Cookie 值提供器
● 服务器变量值提供器
● Session 值提供器
● TempData 值提供器
模型绑定器
1.作用
模型扩展的另一部分是模型绑定器。它们从值提供器系统中获取值,并利用获取的值创建新模型或者填充已有的模型。
模型绑定器,从值提供器中获取值。
ASP .NET MVC 中的默认模型绑定器( 为方便起见,命名为DefaultModelBinder)是一段功能非常强大的代码,它可以对传统类、集合类、列表、数组 甚至字典进行模型绑定。
但是不支持对不改变对象的模型绑定(不可变指的是只能通过构造函数初始化值的类),如果遇见不可变的对象或者类型则默认的模型绑定器就无用了。此时需要自定义模型绑定器
2. 自定义模型绑定器
实现IModelBinder接口的 BinderModel方法
object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
主要是用到ModelBindingContext类
假设要对Point类进行模型绑定(Point类只能通过构造函数进行初始化,所以只能通过自定义模型提供器)
下面是Point类代码和自定义模型绑定器代码
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Web;
- using System.Web.Mvc; //IModelBinder
- namespace MvcApplication1.Sample_ModelBinder
- {
- public class TestModelBinder : IModelBinder
- {
- public object BindModel(ControllerContext controllerContext,
- ModelBindingContext bindingContext)
- {
- var valueProvider = bindingContext.ValueProvider;
- int x = (int)valueProvider.GetValue("X").ConvertTo(typeof(int));
- int y = (int)valueProvider.GetValue("Y").ConvertTo(typeof(int));
- return new Point(x, y);
- }
- }
- public class PointModelBinder : IModelBinder
- {
- //public object BindModel(ControllerContext controllerContext,
- //ModelBindingContext bindingContext)
- //{
- // var valueProvider = bindingContext.ValueProvider;
- // int x = (int)valueProvider.GetValue("X").ConvertTo(typeof(int));
- // int y = (int)valueProvider.GetValue("Y").ConvertTo(typeof(int));
- // return new Point(x, y);
- //}
- private TModel Get<TModel>(ControllerContext controllerContext,ModelBindingContext bindingContext,string name)
- {
- string fullName = name;
- //1.modelname
- if (!String.IsNullOrWhiteSpace(bindingContext.ModelName))
- fullName = bindingContext.ModelName + "." + name;
- //2.,valueProviderResult
- ValueProviderResult valueProviderResult =bindingContext.ValueProvider.GetValue(fullName);
- //3.modelState
- ModelState modelState = new ModelState { Value = valueProviderResult };
- //4.ModelstatebindingContext.ModelState
- bindingContext.ModelState.Add(fullName, modelState);
- //5.null
- ModelMetadata metadata = bindingContext.PropertyMetadata[name];
- string attemptedValue = valueProviderResult.AttemptedValue;
- if (metadata.ConvertEmptyStringToNull&& String.IsNullOrWhiteSpace(attemptedValue))
- attemptedValue = null;
- //6.
- TModel model;
- bool invalidValue = false;
- try
- {
- model = (TModel)valueProviderResult.ConvertTo(typeof(TModel));
- metadata.Model = model; //XX
- }
- catch (Exception)
- {
- model = default(TModel); //int 0.boolfalse,null
- metadata.Model = attemptedValue;
- invalidValue = true; //null
- }
- ///
- IEnumerable<ModelValidator> validators =
- ModelValidatorProviders.Providers.GetValidators(
- metadata,
- controllerContext
- );
- foreach (var validator in validators)
- foreach (var validatorResult in
- validator.Validate(bindingContext.Model))
- modelState.Errors.Add(validatorResult.Message);
- if (invalidValue && modelState.Errors.Count == 0)
- modelState.Errors.Add(
- String.Format(
- "The value '{0}' is not a valid value forr {1}.",
- attemptedValue,
- metadata.GetDisplayName()
- )
- );
- return model;
- }
- public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
- {
- //1.modelname object
- //
- if (!String.IsNullOrEmpty(bindingContext.ModelName) &&
- !bindingContext.ValueProvider.ContainsPrefix(bindingContext.ModelName))
- {
- if (!bindingContext.FallbackToEmptyPrefix)
- return null;
- bindingContext = new ModelBindingContext
- {
- ModelMetadata = bindingContext.ModelMetadata,
- ModelState = bindingContext.ModelState,
- PropertyFilter = bindingContext.PropertyFilter,
- ValueProvider = bindingContext.ValueProvider
- };
- }
- bindingContext.ModelMetadata.Model = new Point();
- return new Point(Get<int>(controllerContext, bindingContext, "X"), Get<int>(controllerContext, bindingContext, "Y"));
- }
- }
- [ModelBinder(typeof(PointModelBinder))]
- //[ModelBinder(typeof(TestModelBinder))]
- public class Point
- {
- private int x;
- public int X
- {
- get { return x; }
- set { x = value;} //
- }
- private int y;
- public int Y
- {
- get { return y;}
- set { y = value;}
- }
- public Point(int x, int y)
- {
- this.x = x;
- this.y = y;
- }
- public Point()
- {
- }
- }
- }
通过调试可以发现ModelBindingContext 包含了
1)值提供器(字符串值提供器,form值提供器,routeDate值提供其,httpfilCollection提供器,childAction值提供器)
2)model 指明了是 point类
3)属性元数据 propertyMetadata 表明了有 x,y两属性

模型绑定器的原理
注明:元数据指的是属性的详细信息,比如:dispalyname特性,属性类型 等等
1. 值提供器中检索值,然后在模型状态中记录值
1)ModelBindingContext的值提供器,默认提供了5种值提供器
2)在模型状态中记录值是因为如果信息错误,可以将错误信息回传显示
2.获得一个描述该属性的模型元数据的副本,然后再决定用户输入值的内容
3.将值转换为目标类型,转换错误则赋值类型的默认值
4.记录错误默认错误信息,回传model
5.使用自定义模型版定器,在类型上面加上
[ModelBinder(typeof(PointModelBinder))]
值提供器 AND 模型绑定器的更多相关文章
- [MVC]自定义模型绑定器,从表单对模型进行赋值
一.奇葩的问题 之前自己造轮子的时候,遇到一个很奇怪的问题,虽然需求很奇葩,但是还是尝试解决了一下 当提交的表单里包含多个重复名称的字段的时候,例如 <form action="/Te ...
- [转]ASP.NET MVC 4 (九) 模型绑定
本文转自:http://www.cnblogs.com/duanshuiliu/p/3706701.html 模型绑定指的是MVC从浏览器发送的HTTP请求中为我们创建.NET对象,在HTTP请求和C ...
- ASP.NET MVC 4 (九) 模型绑定
模型绑定指的是MVC从浏览器发送的HTTP请求中为我们创建.NET对象,在HTTP请求和C#间起着桥梁的作用.模型绑定的一个最简单的例子是带参数的控制器action方法,比如我们注册这样的路径映射: ...
- [转] ASP.NET MVC 模型绑定的功能和问题
摘要:本文将与你深入探究 ASP.NET MVC 模型绑定子系统的核心部分,展示模型绑定框架的每一层并提供扩展模型绑定逻辑以满足应用程序需求的各种方法. 同时,你还会看到一些经常被忽视的模型绑定技术, ...
- ASP.NET MVC 模型绑定
模型绑定指的是MVC从浏览器发送的HTTP请求中为我们创建.NET对象,在HTTP请求和C#间起着桥梁的作用.模型绑定的一个最简单的例子是带参数的控制器action方法,比如我们注册这样的路径映射: ...
- MVC值提供组件ValueProvider的继承关系
MVC请求过程中中各组件调用顺序:值提供组件(IValueProvider)->模型绑定组件(IModelBinder)->模型验证组件 值提供组件接口 public interface ...
- asp.net MVC 自定义模型绑定 从客户端中检测到有潜在危险的 Request.QueryString 值
asp.net mvc 自定义模型绑定 有潜在的Requset.Form 自定义了一个模型绑定器.前端会传过来一些敏感字符.调用bindContext. valueProvider.GetValue( ...
- 第11课 std::bind和std::function(2)_std::bind绑定器
1. 温故知新:std::bind1st和std::bind2nd (1)bind1st.bind2nd首先它们都是函数模板,用于将参数绑定到可调用对象(如函数.仿函数等)的第1个或第2个参数上. ( ...
- 关于QtCharts中的映射器与模型的使用
简述 本文章基于博主在使用QtCharts中一些经验总结,相关了Qt类有QVXYModelMapper,CustomTableModel(一个继承了QAbstractTableModel的类,用于实现 ...
随机推荐
- ALTER TABLE causes auto_increment resequencing, resulting in duplicate entry ’1′ for key
当我用SQLyog尝试修改已有记录的mysql数据表的主键为自动增长时,报出以下错误 ALTER TABLE causes auto_increment resequencing, resulting ...
- css的常用知识点
一.css的引入方式 1.行内引入 直接在标签中定义样式 <p style="background-color: red">test</p> 2.嵌入式引入 ...
- 解决:IDEA unable to import maven project see logs for details问题+java http请求报java.net.SocketException: Permission denied:connect 问题
背景:用IDEA写了一个java发送http请求的maven项目. 运行时,项目报java.net.SocketException: Permission denied:connect问题: 修改po ...
- LightOJ - 1138 (二分+阶乘分解)
题意:求阶乘尾部有Q(1 ≤ Q ≤ 108)个0的最小N 分析:如果给出N,然后求N!尾部0的个数的话,直接对N除5分解即可(因为尾部0肯定是由5*2构成,那么而在阶乘种,2的因子个数要比5少,所以 ...
- springboot的Scheduled定时器不工作
问题情况 使用springboot,使用注解方式启动定时器进行业务调度. 在入口类中加了注解如下: package org.test.xyz; @SpringBootApplication @Enab ...
- Mixed mode assembly is built against version 'v2.0.50727' of the runtime and cannot be loaded in the 4.0 runtime without additional configuration info
Mixed mode assembly is built against version 'v2.0.50727' of the runtime and cannot be loaded in the ...
- 高通平台下安卓opencl小例子
http://blog.csdn.net/wcj0626/article/details/26272019 先到高通的qdn下载adreno GPU SDK,里面有OpenCL的例子.https:// ...
- USACO 简易题解(蒟蒻的题解)
蒟蒻难得可以去比赛,GDOI也快到了,还是认真刷题(不会告诉你之前都在颓废),KPM 神犇既然都推荐刷USACO, 辣就刷刷. 现在蒟蒻还没刷完,太蒟刷得太慢,so 写了的搞个简易题解(没代码,反正N ...
- Linux系统官网下载
CentOS-6.9-x86_64-bin-DVD1.isohttp://archive.kernel.org/centos-vault/6.9/isos/x86_64/CentOS-6.9-x86_ ...
- DPDK l2fwd
dpdk的l2fwd主要做二层转发,代码分析如下. #include <stdio.h> #include <stdlib.h> #include <string.h&g ...