首页 / 网页编程 / ASP.NET / 深入分析ASP.NET Mvc 1.0 – 4. 使用ModelBinder绑定Action的参数
        
            深入分析ASP.NET Mvc 1.0 – 4. 使用ModelBinder绑定Action的参数2011-03-26 博客园 Terry Sun在前一篇文章已经讲叙Controller.Execute(…)方法的执行流程中会调用 ControllerActionInvoker类的 InvokeAction(ControllerContext controllerContext, string actionName)方法,在InvokeAction(…)方法内又调用了GetParameterValues(…) 方法,这个方法为Action中的每个参数赋值,追踪到 GetParameterValues(…)方法内部 会发现其实每个参数的值是由GetParameterValue(…)返回的,观察 GetParameterValue( …)方法的源码:protected virtual object GetParameterValue(ControllerContext  controllerContext, ParameterDescriptor parameterDescriptor) {
       // collect all of the necessary binding  properties
       Type parameterType = parameterDescriptor.ParameterType;
       IModelBinder binder = GetModelBinder (parameterDescriptor);
       IDictionary<string, ValueProviderResult> valueProvider  = controllerContext.Controller.ValueProvider;
       string parameterName =  parameterDescriptor.BindingInfo.Prefix ??  parameterDescriptor.ParameterName;
       Predicate<string> propertyFilter = GetPropertyFilter (parameterDescriptor);
       // 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;
     }
   }