ModelBinder——ASP.NET MVC Model绑定的核心
2012-05-21 08:12
856 查看
Model的绑定体现在从当前请求提取相应的数据绑定到目标Action方法的参数。通过前面的介绍我们知道Action方法的参数通过ParameterDescriptor来描述,ParameterDescriptor的BindingInfo属性表示的ParameterBindingInfo对象具有一个名为ModelBinder的组件用于完成针对当前参数的Model绑定。ModelBinder可以看成是整个Model绑定系统的核心,我们先来认识这个重要的组件。[本文已经同步到《How ASP.NET MVC Works?》中]
目录
一、 ModelBinder
二、CustomModelBinderAttribute与ModelBinderAttribute
三、ModelBinders
四、ModelBinderProvider
IModelBinder的BindModel方法接受两个参数,一个是表示当前的Controller上下文,另一个是表示针对当前Model绑定的上下文,通过类型ModelBindingContext表示。在Controller初始化的时候,Controller上下文已经被创建出来,所以我们只要能够针对当前的Model绑定创建相应的ModelBindingContext,我们就能使用基于某个参数的ModelBinder得到对应的参数值。关于ModelBindingContext的创建我们会在后续部分进行的单独介绍,我们先来介绍一下ModelBinder的提供机制。
在ASP.NET MVC应用编程接口中,CustomModelBinderAttribute具有一个具有如下定义的唯一继承类型ModelBinderAttribute。我们可以通过应用ModelBinderAttribute特性动态地选择用于Model绑定的ModelBinder类型。
从应用在ModelBinderAttribute类型上的AttributeUsageAttribute定义可以看出该特性不仅仅可以应用在参数上,也可以应用类型(接口、枚举、结构和类)上,这意味我们既可以将它应用在Action方法的某个参数上,也可以将它应用在某个参数的类型上。但是ParameterDescriptor只会解析应用在参数上的特性,所以应用在参数对象类型上的ModelBinderAttribute对它是无效的。
为了演示ModelBinderAttribute特性对ParameterDescriptor的影响,我们来进行一个简单的实例演示。在一个通过Visual Studio的ASP.NET MVC项目模板创建的空Web应用中定义了如下几个类型,其中FooModelBinder和BarModelBinder是显现了IModelBinder的自定义ModelBinder类型,而Foo、Bar和Baz是三个将被作为Action方法参数的数据类型,其中Bar上应用了ModelBinderAttribute特性并将ModelBinder类型设置为BarModelBinder。
然后再创建的默认HomeController中定义如下两个Action方法。DoSomething方法具有三个参数,类型分别是Foo、Bar和Baz,在第一个参数上应用了ModelBinderAttribute特性并将ModelBinder类型设置为FooModelBinder。
在默认的Action方法Index中,我们针对HomeController类型的ReflectedControllerDescriptor对象并获取到用于描述Action方法DoSomething的ActionDescriptor对象。最后我们通过该ActionDescriptor对象得到用于描述其三个参数的ParameterDescriptor对象,并将其ModelBinder类西国内呈现出来。当我们运行该程序的时候,会在浏览器中产生如下的输出结果,可以看出对于分别应用在参数和参数类型上的ModelBinderAttribute特性,只有前者会对ParameterDescriptor的ModelBinder的选择造成影响。
ModelBinderDictionary是一个以数据类型(Model类型)为Key,ModelBinder对象为Value的字典,即它定义了针对某种数据类型的ModelBinder。ModelBinderDictionary具有两个GetBinder方法重载用于获取针对某个数据类型的ModelBinder,布尔类型的参数fallbackToDefault表示在数据类型不存在的时候是否采用默认的ModelBinder,基于默认ModelBinder的后备机制会在第一个GetBinder方法重载中采用。在这里默认ModelBinder类型为DefaultModelBinder。
在为某个参数获取相应的ModelBinder的时候,如果对应的ParameterDescriptor的ModelBinder不存在,则通过ModelBinders的静态属性Binders表示获取到当前注册的ModelBinder列表的ModelBinderDictionary对象,并将参数类型作为参数调用其GetBinder方法获取相应ModelBinder对象。
我们根据ModelBinder的提供机制对上面演示的实例进行相应的修改。我们在HomeConroller中添加了一个CheckModelBinder方法,三个参数分别表示用于描述相应Action方法的ActionDescriptor对象、参数名称和类型。在该方法中我们先获取到用于描述制定参数的ParameterDescriptor对象,如果它具有相应的ModelBinder,则将具体的类型名称输出,否则输出通过ModelBinders获取的针对参数类型的ModelBinder类型。
在Index方法中,我们调用CheckModelBinder方法将Action方法DoSomething的三个参数对应的ModelBinder类型呈现出来。当我们运行该程序的时候,在浏览器上会得到如下的输出结果,应用在类型Bar上的BarModelBinder会用于针对参数bar的Model绑定,而参数baz则会使用默认的DefaultModelBinder。
对于上面的这个例子,由于数据类型Baz没有关联ModelBinder注册到通过ModelBinders的静态属性Binders表示的全局ModelBinder列表中,所以才导致DoSomething的baz参数采用默认的DefaultModelBinder。如果我们实现针对数据类型Baz进行了相应的ModelBinder注册,那么被注册的ModelBinder将会自动用于该类型参数的Model绑定。同样是针对上面演示的这个实例,我们定义了如下一个实现了IModelBinder的BazModelBinder。
现在我们希望使用这个BazModelBinder用于针对所有类型为Bar的参数的Model绑定,那么我们可以通过Global.asax在应用启动的时候进行如下的ModelBinder注册。
再次运行我们的程序,在浏览器中会得到如下的输出结果,从中可以清楚地看出我们注册的BazModelBinder并用于baz参数的Model绑定。
我们可以利用ModelBinderProviders为应用注册一组ModelBinderProvider对象为某个数据类型提供相应的ModelBinder。如下面的代码片断所示,静态类型ModelBinderProviders具有一个静态只读属性BinderProviders,其类型ModelBinderProviderCollection实际上是一个型ModelBinderProvider的集合,该集合表示针对当前应用的ModelBinderProvider列表。
通过ModelBinderProviders的静态属性BinderProviders表示的ModelBinderProvider列表最终被ModelBinderDictionary使用。如下面的代码片断所示,ModelBinderDictionary除了具有一个表示基于数据类型的ModelBinder字典(_innerDictionary字段)和一个默认ModelBinder(_defaultBinder)之外,还具有一个ModelBinderProvider列表(_modelBinderProviders字段)。
当ModelBinderDictionary被创建的时候,通过ModelBinderProviders的静态属性BinderProviders表示的ModelBinderProvider列表会用于初始化_modelBinderProviders字段。围绕着ModelBinder的Model绑定系统中的核心组件之间的关系基本上可以通过下图所示的UML来表示。
当我们调用GetBinder或者指定数据类型对应的ModelBinder时,_innerDictionary字段表示的ModelBinder字典会被优先选择。如果数据类型在该字典中找不到,则选择使用通过_modelBinderProviders字段表示的ModelBinderProvider列表进行ModelBinder的提供。只有在两种ModelBinder提供方式均失败的情况下才会选择通过_innerDictionary字段表示的默认ModelBinder。也就是说,如果我们想为某个数据类型定制某种类型的ModelBinder,按照选择优先级具有如下几种方式供我们选择:
将ModelBinderAttribute应用在Action方法的相应参数上并指定相应的ModelBinder类型,或者在参数上应用一个自定义的CustomModelBinderAttribute特性。
通过ModelBinders的静态属性Binders实现针对基于某种数据类型的ModelBinder注册。
自定义ModelBinderProvider实现基于某个数据类型的ModelBinder提供机制,并通过注册当通过ModelBinderProviders的静态属性BinderProviders表示的ModelBinderProvider列表中。
将ModelBinderAttribute应用在数据类型上并制定相应的ModelBinder类型,或者在数据类型上应用一个自定义的CustomModelBinderAttribute特性。
前面三种方式的ModelBinder提供机制我们已经通过实例演示过了,现在我们来演示基于自定义ModelBinderProvider的ModelBinder提供机制。在前面的例子中我们为Foo、Bar和Baz这三种数据类型创建了相应的ModelBinder(FooModelBinder、BarModelBinder和BazModelBinder),现在我们创建如下一个自定义的ModelBinderProvider将两种(数据类型和ModelBinder对象)进行关联。
现在我们需要通过利用Global.asax通过如下的方式在应用启动时将一个我们自定义的MyModelBinderProvider注册到通过ModelBinderProviders的静态属性BinderProviders表示的ModelBinderProvider列表中。
由于MyModelBinderProvider实现了针对Foo、Bar和Baz三种数据类型的ModelBinder的提供,所以我们可以将应用在Action方法参数和数据类型上的ModelBinderAttribute特性删除。再次运行我们的程序,会在浏览器中得到如下的输出结果,从中可以看到DoSomething方法的三个参数此时采用了我们期望的ModelBinder类型。
目录
一、 ModelBinder
二、CustomModelBinderAttribute与ModelBinderAttribute
三、ModelBinders
四、ModelBinderProvider
一、 ModelBinder
用于进行Model绑定的ModelBinder对象实现了接口IModelBinder。如下面的代码片断所示,IModelBinder接口具有唯一的BindModel方法用于实现针对某个参数的绑定操作,该方法的返回值表示的就是最终作为参数值的对象。public interface IModelBinder { object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext); }
IModelBinder的BindModel方法接受两个参数,一个是表示当前的Controller上下文,另一个是表示针对当前Model绑定的上下文,通过类型ModelBindingContext表示。在Controller初始化的时候,Controller上下文已经被创建出来,所以我们只要能够针对当前的Model绑定创建相应的ModelBindingContext,我们就能使用基于某个参数的ModelBinder得到对应的参数值。关于ModelBindingContext的创建我们会在后续部分进行的单独介绍,我们先来介绍一下ModelBinder的提供机制。
二、CustomModelBinderAttribute与ModelBinderAttribute
如果针对某个参数的ParameterDescriptor具有相应的ModelBinder,那么它会被优先选择用于针对该参数的Model绑定,那么ParameterDescriptor的ModelBinder是如何来提供的呢?这是实际上设置一个具有如下定义的CustomModelBinderAttribute特性。抽象类CustomModelBinderAttribute定义了唯一的抽象方法GetBinder用于获取相应的ModelBinder对象。[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Interface | AttributeTargets.Enum | AttributeTargets.Struct | AttributeTargets.Class, AllowMultiple=false, Inherited=false)] public abstract class CustomModelBinderAttribute : Attribute { public abstract IModelBinder GetBinder(); }
在ASP.NET MVC应用编程接口中,CustomModelBinderAttribute具有一个具有如下定义的唯一继承类型ModelBinderAttribute。我们可以通过应用ModelBinderAttribute特性动态地选择用于Model绑定的ModelBinder类型。
[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Interface | AttributeTargets.Enum | AttributeTargets.Struct | AttributeTargets.Class, AllowMultiple=false, Inherited=false)] public sealed class ModelBinderAttribute : CustomModelBinderAttribute { public ModelBinderAttribute(Type binderType); public override IModelBinder GetBinder(); public Type BinderType { [CompilerGenerated] get; } }
从应用在ModelBinderAttribute类型上的AttributeUsageAttribute定义可以看出该特性不仅仅可以应用在参数上,也可以应用类型(接口、枚举、结构和类)上,这意味我们既可以将它应用在Action方法的某个参数上,也可以将它应用在某个参数的类型上。但是ParameterDescriptor只会解析应用在参数上的特性,所以应用在参数对象类型上的ModelBinderAttribute对它是无效的。
为了演示ModelBinderAttribute特性对ParameterDescriptor的影响,我们来进行一个简单的实例演示。在一个通过Visual Studio的ASP.NET MVC项目模板创建的空Web应用中定义了如下几个类型,其中FooModelBinder和BarModelBinder是显现了IModelBinder的自定义ModelBinder类型,而Foo、Bar和Baz是三个将被作为Action方法参数的数据类型,其中Bar上应用了ModelBinderAttribute特性并将ModelBinder类型设置为BarModelBinder。
public class FooModelBinder : IModelBinder { public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) { throw new NotImplementedException(); } } public class BarModelBinder : IModelBinder { public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) { throw new NotImplementedException(); } } public class Foo { } [ModelBinder(typeof(BarModelBinder))] public class Bar { } public class Baz { }
然后再创建的默认HomeController中定义如下两个Action方法。DoSomething方法具有三个参数,类型分别是Foo、Bar和Baz,在第一个参数上应用了ModelBinderAttribute特性并将ModelBinder类型设置为FooModelBinder。
public class HomeController : Controller { public void Index() { ControllerDescriptor controllerDescriptor = new ReflectedControllerDescriptor(typeof(HomeController)); ActionDescriptor actionDescriptor = controllerDescriptor.FindAction(ControllerContext, "DoSomething"); IModelBinder foo = actionDescriptor.GetParameters().First(p => p.ParameterName == "foo").BindingInfo.Binder; IModelBinder bar = actionDescriptor.GetParameters().First(p => p.ParameterName == "bar").BindingInfo.Binder; IModelBinder baz = actionDescriptor.GetParameters().First(p => p.ParameterName == "baz").BindingInfo.Binder; Response.Write(string.Format("foo: {0}<br/>", null == foo? "N/A": foo.GetType().Name)); Response.Write(string.Format("bar: {0}<br/>", null == bar ? "N/A" : bar.GetType().Name)); Response.Write(string.Format("baz: {0}<br/>", null == baz ? "N/A" : baz.GetType().Name)); } public void DoSomething([ModelBinder(typeof(FooModelBinder))]Foo foo,Bar bar, Bar baz) {} }
在默认的Action方法Index中,我们针对HomeController类型的ReflectedControllerDescriptor对象并获取到用于描述Action方法DoSomething的ActionDescriptor对象。最后我们通过该ActionDescriptor对象得到用于描述其三个参数的ParameterDescriptor对象,并将其ModelBinder类西国内呈现出来。当我们运行该程序的时候,会在浏览器中产生如下的输出结果,可以看出对于分别应用在参数和参数类型上的ModelBinderAttribute特性,只有前者会对ParameterDescriptor的ModelBinder的选择造成影响。
foo: FooModelBinder bar: N/A baz: N/A
三、ModelBinders
如果我们不曾通过ModelBinderAttribute特性为某个Action方法参数的ModelBinder类型进行显式定制,默认采用的Model是通过静态类型ModelBinders来提供的。如下面的代码片断所示,ModelBinders具有一个静态只读属性Binders,表示当前注册ModelBinder列表,其类型为ModelBinderDictionary。public static class ModelBinders { public static ModelBinderDictionary Binders { get; } } public class ModelBinderDictionary : IDictionary<Type, IModelBinder>, ICollection<KeyValuePair<Type, IModelBinder>>, IEnumerable<KeyValuePair<Type, IModelBinder>>, IEnumerable { //其他成员 public IModelBinder GetBinder(Type modelType); public virtual IModelBinder GetBinder(Type modelType, bool fallbackToDefault); }
ModelBinderDictionary是一个以数据类型(Model类型)为Key,ModelBinder对象为Value的字典,即它定义了针对某种数据类型的ModelBinder。ModelBinderDictionary具有两个GetBinder方法重载用于获取针对某个数据类型的ModelBinder,布尔类型的参数fallbackToDefault表示在数据类型不存在的时候是否采用默认的ModelBinder,基于默认ModelBinder的后备机制会在第一个GetBinder方法重载中采用。在这里默认ModelBinder类型为DefaultModelBinder。
在为某个参数获取相应的ModelBinder的时候,如果对应的ParameterDescriptor的ModelBinder不存在,则通过ModelBinders的静态属性Binders表示获取到当前注册的ModelBinder列表的ModelBinderDictionary对象,并将参数类型作为参数调用其GetBinder方法获取相应ModelBinder对象。
我们根据ModelBinder的提供机制对上面演示的实例进行相应的修改。我们在HomeConroller中添加了一个CheckModelBinder方法,三个参数分别表示用于描述相应Action方法的ActionDescriptor对象、参数名称和类型。在该方法中我们先获取到用于描述制定参数的ParameterDescriptor对象,如果它具有相应的ModelBinder,则将具体的类型名称输出,否则输出通过ModelBinders获取的针对参数类型的ModelBinder类型。
public class HomeController : Controller { //其他成员 public void Index() { ControllerDescriptor controllerDescriptor = new ReflectedControllerDescriptor(typeof(HomeController)); ActionDescriptor actionDescriptor = controllerDescriptor.FindAction(ControllerContext, "DoSomething"); CheckModelBinder(actionDescriptor, "foo", typeof(Foo)); CheckModelBinder(actionDescriptor, "bar", typeof(Bar)); CheckModelBinder(actionDescriptor, "baz", typeof(Baz)); } private void CheckModelBinder(ActionDescriptor actionDescriptor, string parameterName, Type modelType) { ParameterDescriptor parameterDescriptor = actionDescriptor.GetParameters().First(p=>p.ParameterName == parameterName); IModelBinder modelBinder = parameterDescriptor.BindingInfo.Binder ?? ModelBinders.Binders.GetBinder(modelType); Response.Write(string.Format("{0}: {1}<br/>", parameterName, null == modelBinder ? "N/A" : modelBinder.GetType().Name)); } }
在Index方法中,我们调用CheckModelBinder方法将Action方法DoSomething的三个参数对应的ModelBinder类型呈现出来。当我们运行该程序的时候,在浏览器上会得到如下的输出结果,应用在类型Bar上的BarModelBinder会用于针对参数bar的Model绑定,而参数baz则会使用默认的DefaultModelBinder。
foo: FooModelBinder bar: BarModelBinder baz: DefaultModelBinder
对于上面的这个例子,由于数据类型Baz没有关联ModelBinder注册到通过ModelBinders的静态属性Binders表示的全局ModelBinder列表中,所以才导致DoSomething的baz参数采用默认的DefaultModelBinder。如果我们实现针对数据类型Baz进行了相应的ModelBinder注册,那么被注册的ModelBinder将会自动用于该类型参数的Model绑定。同样是针对上面演示的这个实例,我们定义了如下一个实现了IModelBinder的BazModelBinder。
public class BazModelBinder : IModelBinder { public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) { throw new NotImplementedException(); } }
现在我们希望使用这个BazModelBinder用于针对所有类型为Bar的参数的Model绑定,那么我们可以通过Global.asax在应用启动的时候进行如下的ModelBinder注册。
public class MvcApplication : System.Web.HttpApplication { //其他成员 protected void Application_Start() { //其他操作 ModelBinders.Binders.Add(typeof(Baz), new BazModelBinder()); } }
再次运行我们的程序,在浏览器中会得到如下的输出结果,从中可以清楚地看出我们注册的BazModelBinder并用于baz参数的Model绑定。
foo: FooModelBinder bar: BarModelBinder baz: BazModelBinder
四、ModelBinderProvider
ASP.NET MVC的Model绑定系统还涉及到另一个重要的组件ModelBinderProvider。顾名思义,ModelBinderProvider专门用于提供相应的ModelBinder对象,它们均实现了IModelBinderProvider面的代码片断所示,IModelBinderProvider接口定义了唯一的GetBinder方法用于根据数据类型获取相应的ModelBinder对象。不过在ASP.NET MVC现有的应用编程接口中并没有定义任何一个实现该接口的ModelBinderProvider类型。public interface IModelBinderProvider { IModelBinder GetBinder(Type modelType); }
我们可以利用ModelBinderProviders为应用注册一组ModelBinderProvider对象为某个数据类型提供相应的ModelBinder。如下面的代码片断所示,静态类型ModelBinderProviders具有一个静态只读属性BinderProviders,其类型ModelBinderProviderCollection实际上是一个型ModelBinderProvider的集合,该集合表示针对当前应用的ModelBinderProvider列表。
public static class ModelBinderProviders { public static ModelBinderProviderCollection BinderProviders { get; } } public sealed class ModelBinderProviderCollection : Collection<IModelBinderProvider> { //省略成员 }
通过ModelBinderProviders的静态属性BinderProviders表示的ModelBinderProvider列表最终被ModelBinderDictionary使用。如下面的代码片断所示,ModelBinderDictionary除了具有一个表示基于数据类型的ModelBinder字典(_innerDictionary字段)和一个默认ModelBinder(_defaultBinder)之外,还具有一个ModelBinderProvider列表(_modelBinderProviders字段)。
public class ModelBinderDictionary { //其他成员 private IModelBinder _defaultBinder; private readonly Dictionary<Type, IModelBinder> _innerDictionary; private ModelBinderProviderCollection _modelBinderProviders; }
当ModelBinderDictionary被创建的时候,通过ModelBinderProviders的静态属性BinderProviders表示的ModelBinderProvider列表会用于初始化_modelBinderProviders字段。围绕着ModelBinder的Model绑定系统中的核心组件之间的关系基本上可以通过下图所示的UML来表示。
当我们调用GetBinder或者指定数据类型对应的ModelBinder时,_innerDictionary字段表示的ModelBinder字典会被优先选择。如果数据类型在该字典中找不到,则选择使用通过_modelBinderProviders字段表示的ModelBinderProvider列表进行ModelBinder的提供。只有在两种ModelBinder提供方式均失败的情况下才会选择通过_innerDictionary字段表示的默认ModelBinder。也就是说,如果我们想为某个数据类型定制某种类型的ModelBinder,按照选择优先级具有如下几种方式供我们选择:
将ModelBinderAttribute应用在Action方法的相应参数上并指定相应的ModelBinder类型,或者在参数上应用一个自定义的CustomModelBinderAttribute特性。
通过ModelBinders的静态属性Binders实现针对基于某种数据类型的ModelBinder注册。
自定义ModelBinderProvider实现基于某个数据类型的ModelBinder提供机制,并通过注册当通过ModelBinderProviders的静态属性BinderProviders表示的ModelBinderProvider列表中。
将ModelBinderAttribute应用在数据类型上并制定相应的ModelBinder类型,或者在数据类型上应用一个自定义的CustomModelBinderAttribute特性。
前面三种方式的ModelBinder提供机制我们已经通过实例演示过了,现在我们来演示基于自定义ModelBinderProvider的ModelBinder提供机制。在前面的例子中我们为Foo、Bar和Baz这三种数据类型创建了相应的ModelBinder(FooModelBinder、BarModelBinder和BazModelBinder),现在我们创建如下一个自定义的ModelBinderProvider将两种(数据类型和ModelBinder对象)进行关联。
public class MyModelBinderProvider : IModelBinderProvider { public IModelBinder GetBinder(Type modelType) { if (modelType == typeof(Foo)) { return new FooModelBinder(); } if (modelType == typeof(Bar)) { return new BazModelBinder(); } if (modelType == typeof(Baz)) { return new BazModelBinder(); } return null; } }
现在我们需要通过利用Global.asax通过如下的方式在应用启动时将一个我们自定义的MyModelBinderProvider注册到通过ModelBinderProviders的静态属性BinderProviders表示的ModelBinderProvider列表中。
public class MvcApplication : System.Web.HttpApplication { //其他成员 protected void Application_Start() { //其他操作 ModelBinderProviders.BinderProviders.Add(new MyModelBinderProvider()); } }
由于MyModelBinderProvider实现了针对Foo、Bar和Baz三种数据类型的ModelBinder的提供,所以我们可以将应用在Action方法参数和数据类型上的ModelBinderAttribute特性删除。再次运行我们的程序,会在浏览器中得到如下的输出结果,从中可以看到DoSomething方法的三个参数此时采用了我们期望的ModelBinder类型。
foo: FooModelBinder bar: BarModelBinder baz: BazModelBinder
相关文章推荐
- ModelBinder——ASP.NET MVC Model绑定的核心
- ModelBinder——ASP.NET MVC Model绑定的核心
- 通过实例模拟ASP.NET MVC的Model绑定的机制:集合+字典
- asp.net mvc源码分析-DefaultModelBinder 自定义的普通数据类型的绑定和验证
- ASP.NET MVC Model绑定(一)
- ASP.NET MVC Model绑定(一)
- ASP.NET MVC Model绑定
- ASP.NET MVC Model绑定(六)
- Asp.net MVC中提交集合对象,实现Model绑定
- 通过实例模拟ASP.NET MVC的Model绑定机制:数组
- ASP.NET MVC以ModelValidator为核心的Model验证体系: ModelValidator
- ASP.NET MVC Model绑定(六)
- 通过实例模拟ASP.NET MVC的Model绑定机制:简单类型+复杂类型
- 通过实例模拟ASP.NET MVC的Model绑定机制:简单类型+复杂类型
- ASP.NET MVC Model绑定(一)
- ASP.NET MVC Model绑定(五)
- ASP.NET MVC Model绑定(五)
- 使用ModelBinder绑定IPrincipal (User)简化ASP.NET MVC单元测试
- 通过实例模拟ASP.NET MVC的Model绑定的机制:集合+字典
- ASP.NET MVC Model绑定(六)