代码中直接根据模型名称(即参数名称)从请求的文件中获取文件数据,简单直接。
但在模型绑定中很少有如文件这种特殊类型的绑定,更多的是一些基础类型以及自定义类型的绑定,而微软并没有针对每一个基础类型都创建了对应的绑定器,所有的一切都是通过DefaultModelBinder完成的,所以DefaultModelBinder的绑定过程相对于特定类型的模型绑定过程来说相对要复杂。
DefaultModelBinder的模型绑定过程上面提到了模型绑定的大部分情况是使用DefaultModelBinder完成的,下面就对该绑定器如何完成模型绑定进行介绍,先上代码:
上面代码做了以下几件事:
1. 确保有足够的栈空间来执行.Net中平均大小的函数。
2. 如果模型名称不为空、数据源中不包含以该模型名称为前缀的值、并且参数绑定信息没有前缀时,重新初始化绑定上下文,相比原有上下文去除FallbackToEmptyPrefix以及ModelName属性并将该模型视为复杂模型:
注:上面这种情况可参考《ASP.NET没有魔法——ASP.NET MVC 模型绑定》文章中的例子,该例子中存在参数名obj,但是QueryString中没有使用obj作为前缀,action参数也没有使用bind特性指定前缀,这样的类型将被视为复杂类型,如下图:
3. 获取是否验证标记,并根据模型名称从ValueProvider中获取数据,获取的数据为ValueProviderResult类型,如果该结果存在那么进行简单模型绑定。(注:ValueProviderResult负责简单类型转换,后续介绍,另外这里的验证涉及到.Net中System.Web的基础实现,所以不再进行深入介绍)
4. 如果模型属于复杂模型,则进行复杂模型绑定。
默认模型绑定器中看到了简单类型与复杂类型概念的使用,从代码中看出模型绑定的核心内容也存在于简单、复杂模型的绑定过程中。
简单模型绑定 之前介绍了简单类型,实际上就是可以从字符串直接转换的类型,除此之外还可以通过自定义类型转换器的方式将复杂类型转换为简单类型。
那么对于简单模型绑定来说,实际上核心就是获取到对应的值后,使用类型转换器将获取到的值转换为目标类型。下面是简单模型绑定的实现代码:
根据代码可以看出简单模型绑定核心如下:
1. 如果模型类型与从值提供器中获取的类型一致,那么不需要转换就可以直接返回。
2. 类型转换的核心方法是DefaultModelBinder.ConvertProviderResult,实际是获取类型转换器完成了转换功能,最终转换代码如下(ValueProviderResult的ConvertSimpleType方法,更多细节可参考反编译代码):
3. 简单模型的转换考虑到了数组类型以及集合类型的转换。
复杂模型绑定一般来说基本类型和一些常用的类型均为简单类型,而复杂模型实际上是由一系列简单类型组成的,所以复杂模型的绑定是将其拆分成一个个简单类型完成绑定后再组装的过程,其主要代码如下(由于完整代码较多,本文只介绍关键点,更多信息可参考DefaultModelBinder的反编译源码):