// finally, call into the binder ModelBindingContext bindingContext = new ModelBindingContext() { FallbackToEmptyPrefix = (parameterDescriptor.BindingInfo.Prefix == null), // only fall back if prefix not specified ModelName = parameterName, ModelState = controllerContext.Controller.ViewData.ModelState, ModelType = parameterType, PropertyFilter = propertyFilter, ValueProvider = valueProvider }; object result = binder.BindModel(controllerContext, bindingContext); return result; }代码的逻辑分为:获取继承了IModelBinder接口的对象执行IModelBinder对象的BindModel(…)方法并返回Action的参数值继承IModelBinder接口的对象有三个类:DefaultModelBinder, FormCollectionModelBinder和HttpPostedFileBaseModelBinder在GetParameterValue(…)方法中可以看到由GetModelBinder(parameterDescriptor) 负责返回IModelBinder对象,但他是如何确定返回哪个ModeBinder的呢?当Action的参数类型为FormCollection时,GetParameterValue(…)方法返回 FormCollectoinModelBinder对象当Action的参数类型为HttpPostedFileBase时,GetParameterValue(…)方法返回 HttpPostedFileBaseModelBinder对象当Action的参数类型除了FormCollection和HttpPostedFileBase外(int, string, boolean或强类型),GetParameterValue(…)方法返回DefaultModelBinder对象, DefaultModelBinder也是最常用的ModelBinder来深入到GetModelBinder(…)方法的内部private IModelBinder GetModelBinder(ParameterDescriptor parameterDescriptor) { // look on the parameter itself, then look in the global table return parameterDescriptor.BindingInfo.Binder ?? Binders.GetBinder(parameterDescriptor.ParameterType); }通常情况下IModelBinder都是由 Binders.GetBinder (parameterDescriptor.ParameterType)返回, Binders属性调用ModelBinders.Binders 返回ModelBinderDictionary的静态实例,在调用 ModelBinders.Binders属性返回 ModelBinderDictionary对象之前先初始化 ModelBinderDictionary对象并将 HttpPostedFileBaseModelBinder保存到 ModelBinderDictionary对象中(代码如下),最 后其实是调用ModelBinderDictionary的GetBinder()方法返回的IModelBinder对象。public static class ModelBinders { private static readonly ModelBinderDictionary _binders = CreateDefaultBinderDictionary();
public static ModelBinderDictionary Binders { get { return _binders; } }
private static ModelBinderDictionary CreateDefaultBinderDictionary() { // We can"t add a binder to the HttpPostedFileBase type as an attribute, so we"ll just // prepopulate the dictionary as a convenience to users.
ModelBinderDictionary binders = new ModelBinderDictionary() { { typeof(HttpPostedFileBase), new HttpPostedFileBaseModelBinder() } }; return binders; }