MVC系统学习3—ModelBinder
在ASP.NET MVC中,每个请求都被映射到一个Action方法,我们可以在action的方法中定义相应类型的参数,View中通过post、get方式提交的request参数,只要名称一致就会对应到相应的action参数,一切似乎理所当然,但是请注意我们的http是基于文本协议的,提交上去的参数应该是被认为是字符串形式,但是我们可以在action中定义string类型之外的其他参数,如int,datetime。在提交到action进行请求的过程里肯定有一个转换。
MVC框架里实现这个转换的就是DefaultModelBinder,DefaultModelBinder实现了IModelBinder接口,该接口的代码如下:
public interface IModelBinder { object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext); } |
DefaultModelBinder能实现如下类型的转换:
模型类,例如 Person、Address 或 Product。
集合,如 ICollection(Of T)、IList(Of T) 或 IDictionary(Of TKey, TValue)。
如果研究MVC的源码我们可以发现, 调用action最终是由ControllerActionInvoker类的InvokeAction方法实现,这个方法里首先会获取调用action所需要的参数,即GetParametersValues方法。这个方法会有一个IModelBinder的选择过程和原则:
- 尝试从附加在参数的CustomModelBinderAttribute特性获取
- 尝试从ModelBinders.Binders集合中按参数类型检索
- 尝试从附加在参数的类型的CustomModelBinderAttribute特性获取
- 使用ModelBinders.Binders.DefaultBinder
如果DefaultModelBinder不能实现我们所需要的转换功能,则我们可以自己定义实现IModelBinder接口的ModelBinder。这种情况现在暂时还没碰到过,通过老赵的一片博客的例子来联系,例如当我们从客户端接口一个可以转换成datetime的类型时,我们希望可以自动转换成某种形式的DateTime。
public class DateTimeModelBinder : IModelBinder
{
public string Format { get; private set; } public DateTimeModelBinder(string format)
{
this.Format = format;
} public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
object value=bindingContext.ValueProvider.GetValue(bindingContext.ModelName).RawValue;
if(value is string)
{
return DateTime.ParseExact((string)value, this.Format, null);
}
else
{
return value;
}
}
}
定义好了ModelBinder,怎么让框架能够使用它,上面讲到了框架中IModelBinder的选择过程和原则。因此我们可以有这么几种实现方法:
1.利用CustomerModelBinderAttribute,写一个类来实现它的GetBinder方法。
public class DateTimeAttribute : CustomModelBinderAttribute
{
public string Format { get; private set; } public DateTimeAttribute(string format)
{
this.Format = format;
} public override IModelBinder GetBinder()
{
return new DateTimeModelBinder(this.Format);
} }
public ActionResult Test([DateTime("yyyy-MM-dd")]DateTime date) |
2.通过在全局文件中想ModelBinders集合添加我们自定义的ModelBinder
MvcAppDemo.Models.DateTimeModelBinder dateTimeBinder = new Models.DateTimeModelBinder("yyyy-MM-dd"); ModelBinders.Binders.Add(typeof(DateTime), dateTimeBinder); |
public ActionResult Test(DateTime date) |
3.通过向我们参数的类型添加CustomerModelBinderAttribute来实现,但是这里DateTime是基本类型,这里通过另外一个例子来实现。蛋疼下,自己定义一个实体,然后实现这个实体的转换。
Blog实体:
[BlogBinder]
public class Blog
{
public string Title { get; set; }
public string Content { get; set; }
public string Author { get; set; }
public DateTime PostDate { get; set; }
}
自定义的ModelBinder:
public class BlogBinder : IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
object model = Activator.CreateInstance(bindingContext.ModelType);
PropertyDescriptorCollection col = TypeDescriptor.GetProperties(model);
foreach (PropertyDescriptor item in col)
{
string value=bindingContext.ValueProvider.GetValue(item.Name).AttemptedValue;
item.SetValue(model, Convert.ChangeType(value,item.PropertyType));
}
return model;
}
}
实现CustomerModelAttribute:
public class BlogBinderAttribute : CustomModelBinderAttribute
{
public override IModelBinder GetBinder()
{
return new BlogBinder();
}
}
其实实现自定义ModelBinder的思路很简单,就是通过反射获取我们的绑定类型的各个成员,接下来以各个成员的名称为键到bindingContext中去找值,接下来进行类型转换,然后再赋值给我们的模型。这个实现的过程中有碰到两个问题
1.类型转换,如果我不适用Convert.ChangeType(object value,Type convertType),而是使用TypeConvert.ConvertTo(object value,destinationType),在转换DateTime类型时会出错?这时为什么?
2.在使用反射进行转换的时候可以利用TypeDescriptor.GetProperties(model)和PropertyDescriptor,自己使用Type和PropertyInfo也同样可以使用,在MVC里面很多地方使用了TypeDescriptor,或者可以见到以Descriptor为后缀的类。TypeDescriptor和Type有什么区别?
MVC系统学习3—ModelBinder的更多相关文章
- MVC系统学习1—MVC执行流程
用MVC来做开发也有一段时间了,但是感觉一直没入门,就徘徊在似懂非懂的层次,和去年刚毕业学习WebForm时一样,当时通过张子阳老兄的几篇文章,明白了请求处理流程,页面生命周期才真正明白了WebFor ...
- MVC系统学习5——验证
其实关于Mvc的验证在上一篇已经有讲过一些了,可以通过在我们定义的Model上面添加相应的System.ComponentModel.DataAnnotations空间下的验证属性.在服务器端通过Mo ...
- MVC系统学习6—Filter
Mvc的过滤器是特性类,可以使我们在执行Action之前,执行Action之后,执行Action发生异常时,编写相关的处理代码实现某些逻辑.下面是四个基本的Filter接口. 上面这四个基本的Filt ...
- MVC系统学习4—ModelMetaData
在Mvc R2中,新引入了一些扩展方法,如后面带一个for的方法,这些扩展方法会根据Model的属性自定生成相应的Html元素,如Html.EditFor(Model=>Model.IsAppr ...
- MVC系统学习2—MVC路由
在MVC下不是通过对物理文件的映射来实行访问的,而是通过定义后的路由Url来实现访问的.在前一篇讲到我们是在全局文件下进行路由配置. routes.MapRoute( & ...
- Mvc系统学习9——Areas学习
在Mvc2.0中,新增加了一个特性就是Areas.在没有有使用Areas的情况下,我们的Mvc项目组织是下面这样的.当项目庞大的时候,Controllers,Model,View文件下下面势必会有很多 ...
- MVC系统学习7—Action的选择过程
在Mvc源码的ControllerActionInvoker的InvokeAction方法里面有一个FindAction方法,FindAction方法在ControllerDescriptor里面定义 ...
- MVC系统学习8——AsyncController
关于为什么使用异步Controller,这里不做备忘,三岁小孩都懂.主要的备忘是如何使用AsyncController. //这个action以Async结尾,并且返回值是void public vo ...
- MVC学习系列——ModelBinder扩展
在MVC系统中,我们接受数据,运用的是ModelBinder 的技术. MVC学习系列——ActionResult扩展在这个系列中,我们自定义了XmlResult的返回结果. 那么是不是意味着能POS ...
随机推荐
- 初学JDBC,获取插入记录的主键、执行批量操作
一.获取插入记录主键值 在创建语句的地方使用Statement.RETURN_GENERATED_KEYS标识一下,然后通过getGeneratedKeys方法获得 preparedStatement ...
- JavaScript入门培训材料(Copy至此以作备份)
JavaScript简明学习教程 2014年5月31日 目录 一.说明... 2 二.准备知识... 2 (一)HTML. 2 (二)DOM.. 3 三.JavaScript简介... 3 四.Jav ...
- MACD、BOLL、KDJ 三大组合精准把握趋势与买卖!
先看示意图,下图是布林线的3个轨道,其他都是股价走势 图1 股价,在布林线上轨.下轨之间运作.准确说,这话是不符合逻辑的,不是先有的轨道,然后股价再按照轨道运动.因为轨道是跟股价同时变化的.但是,股价 ...
- SqlServer Link 链接服务器的使用
--创建linked exec sp_addlinkedserver 'a','','SQLNCLI','your ipaddress' --登陆linked exec sp_addlinkedsrv ...
- 下载安装resin-3.X服务器并配置到myeclipse
前提是先安装jdk,具体自己安装. 1.到resin官网http://www.caucho.com/download/下载相应压缩包,比如resin-3.2.0.zip 2.解压下载的resin-3. ...
- 关于Java类加载双亲委派机制的思考(附一道面试题)
预定义类加载器和双亲委派机制 JVM预定义的三种类型类加载器: 启动(Bootstrap)类加载器:是用本地代码实现的类装入器,它负责将 <Java_Runtime_Home>/lib下面 ...
- UVa 11464 - Even Parity
解题报告:题目大意有一个N×N的矩阵,矩阵中的元素只有1或0,如果说对于一个矩阵,它的所有的点的上下左右的点的和是偶数,则称这个矩阵为偶数矩阵,现在给你一个任意的矩阵,要求的是如果要把这个矩阵变成偶数 ...
- [Effective JavaScript 笔记] 第10条:避免使用with
with特性,提供的任何“便利”都更让其变得不可靠和低效率. with语句的用法,可以很方便地避免对对象的重复引用.上面的代码整理成下面的形式 function status(info){ var w ...
- change column to bigint
今天存储数据的时候报错,发现是3435065640超出了常规int的存储长度, RangeError (3435065640 is out of range for ActiveRecord::Typ ...
- Coursera台大机器学习技法课程笔记04-Soft-Margin Support Vector Machine
之前的SVM非常的hard,要求每个点都要被正确的划分,这就有可能overfit,为此引入了Soft SVM,即允许存在被错分的点,将犯的错放在目 标函数中进行优化,非常类似于正则化. 将Soft S ...