• 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(***);

    }

  • 相关阅读:
    JSONP原理
    什么是跨域,如何解决
    工程化与模块化开
    vue双向数据绑定原理
    vuex原理
    BFC 原理
    http状态码 301、302区别
    用户页面打开很慢,有哪些优化方式?
    webpack打包
    Promise 原理
  • 原文地址:https://www.cnblogs.com/ghhlyy/p/2942327.html
Copyright © 2020-2023  润新知