上一篇《ASP.NET没有魔法——ASP.NET MVC 模型绑定解析(上篇)》文章介绍了ASP.NET MVC模型绑定的相关组件和概念,本章将介绍Controller在执行时是如何通过这些组件完成模型绑定功能的,本章的主要内容有:
●
○
○
○
○
●
○
○
●
之前的文章介绍过MVC中Controller的创建与执行(可参考:《ASP.NET没有魔法——ASP.NET MVC Controller的实例化与执行》),其执行过程包含临时数据加载、Action方法名称获取、Action方法执行及临时数据保存。
而模型绑定过程实际上就包含在Action方法的执行(ActionInvoker.InvokeAction方法)中,之前的文章《ASP.NET没有魔法——ASP.NET MVC 过滤器(Filter)》也通过从过滤器的角度介绍了Action的执行,其中一点就是当授权过滤器执行完成并通过授权后将开始执行其它过滤器与Action方法,如下图:
而Action方法的执行核心代码如下:
代码中的GetParameterValues方法的作用就是根据Controller的上下文以及Action的描述信息来获取Action参数的过程,也就是模型绑定的过程,其代码如下:
上面代码就是获取Action的参数数组,然后遍历这个数组,通过GetParameterValue方法完成单个参数的绑定工作,最后以参数名称为Key,绑定后的值为对象存储在字典中返回。下面是GetParameterValue方法的具体代码:
从代码看来整个绑定过程有如下几个步骤:
1. 根据参数获取ModelBinder。
2. 从Controller中获取值提供器。
3. 创建模型绑定上下文,该上下文中包含Metadata、模型名称、值提供器等内容。
4. 通过获取的ModelBinder完成模型绑定。
接下来就对这些核心步骤进行分析。
代码中调用GetModelBinder方法,根据参数信息获取一个ModelBinder,下图是实现代码:
从代码中可以看出,获取ModelBinder的方式有两种,首先从通过参数描述信息(ParameterDescriptor)来获取通过特性标记的方式应用到该参数的ModelBinder,其核心代码如下(ParameterDescriptor默认使用的类型是ReflectedParameterDescriptor,通过反射的方式获取特性):
注:更多关于通过特性应用自定义ModelBinder的内容可参考:https://www.codeproject.com/articles/605595/asp-net-mvc-custom-model-binder
当参数上没有通过特性指定ModelBinder时,将通过Binders根据参数类型来获取ModelBinder,这里的Binders实际上就是ModelBinderDictionary,前面介绍过这个字典中以ModelBinder的类型名称为Key保存了所有的ModelBinder,ModelBinderDictionary的GetBinder方法如下:
首先通过ModelBinderProviders查找(注:默认情况下ASP.NET MVC没有使用ModelBinderProvider:),然后再通过类型名称在字典中匹配对应的ModelBinder,最后从模型类型上找是否通过特性指定了Modelbinder。
如果以上都找不到那么使用默认的ModelBinder,ModelBinderDictionary的结构如下图: