mvc源码解读(17)数据绑定组件ModelBinder之ModelBinders

     在之前的文章中我们讲过,在获取ModelBinder的时候优先选择的是应用在Action参数上的CustomModelBinder,具体的实现是在静态类ModelBinders里面的GetBinderFromAttributesImpl方法:

 private static IModelBinder GetBinderFromAttributesImpl(CustomModelBinderAttribute[] attrs, Func<string> errorMessageAccessor)

我们在分析源码的时候可以看到ModelBinder有一个Binders属性,是对ModelBinderDictionary类的一个封装,具体如下:

 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() },                

                      {typeof(byte[]), new ByteArrayModelBinder() },                

                      {typeof(Binary), new LinqBinaryModelBinder() }            

                        };            

                 return binders;        

}

 mvc应用程序中提供了三种默认的ModelBinder供我们使用,我们逐一来看看。HttpPostedFileBaseModelBinder里面的成员如下:

public class HttpPostedFileBaseModelBinder : IModelBinder {

        public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) {            

            HttpPostedFileBase theFile = controllerContext.HttpContext.Request.Files[bindingContext.ModelName];            

            return ChooseFileOrNull(theFile);        

       }

        // helper that returns the original file if there was content uploaded, null if empty        

        internal static HttpPostedFileBase ChooseFileOrNull(HttpPostedFileBase rawFile) {            

            // case 1: there was no <input type="file" ... /> element in the post            

                    if (rawFile == null) {return null;}

            // case 2: there was an <input type="file" ... /> element in the post, but it was left blank            

                if (rawFile.ContentLength == 0 && String.IsNullOrEmpty(rawFile.FileName)) {return null;}

            // case 3: the file was posted            

              return rawFile;        

        }

 }

HttpPostedFileBaseModelBinder用于客户端上传文件时相关的绑定,看红色的英文注释,不解释。还有就是字节数组的绑定ByteArrayModelBinder,具体实现如下:

 public class ByteArrayModelBinder : IModelBinder {        

            public virtual object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) {

                      ValueProviderResult valueResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);

                       // case 1: there was no <input ... /> element containing this data            

                      if (valueResult == null) {return null;}

                      string value = valueResult.AttemptedValue;

                      // case 2: there was an <input ... /> element but it was left blank            

                      if (String.IsNullOrEmpty(value)) {return null;}

                      // Future proofing. If the byte array is actually an instance of System.Data.Linq.Binary            

                      // then we need to remove these quotes put in place by the ToString() method.            

                      string realValue = value.Replace("\"", String.Empty);            

                      return Convert.FromBase64String(realValue);        

            }    

}

还有就是LinqBinaryModelBinder的绑定,该类是继承了字节数组ByteArrayModelBinder类,具体的实现如下:

 public class LinqBinaryModelBinder : ByteArrayModelBinder {        

           public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) {            

                 byte[] byteValue = (byte[])base.BindModel(controllerContext, bindingContext);            

                  if (byteValue == null) {return null;}

                  return new Binary(byteValue);

         }    

}

     我们之前介绍过mvc中获取ModelBinder的顺序,在Action方法的参数中没有标注CustomModelBinderAttribute和ModelBinderProviders中的BinderProviders中也没有提供ModelBinder的话,就会在全局文件中查找,如同ModelBinderProviders中的BinderProviders在Application_Start注册一样,ModelBinders提供的ModelBinder也是在全局文件的Application_Start注册:

protected void Application_Start()
 {  

       ModelBinders.Binders.Add(***);

}

原文地址:https://www.cnblogs.com/ghhlyy/p/2942327.html