zoukankan      html  css  js  c++  java
  • 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(***);

    }

  • 相关阅读:
    云原生生态周报 Vol. 16 | CNCF 归档 rkt,容器运行时“上古”之战老兵凋零
    Knative 基本功能深入剖析:Knative Eventing 之 Sequence 介绍
    基于 K8s 做应用发布的工具那么多, 阿里为啥选择灰姑娘般的 Tekton ?
    Serverless 的喧哗与骚动(一)附Serverless行业发展回顾
    239. Sliding Window Maximum
    237. Delete Node in a Linked List
    146. LRU Cache
    140. Word Break II
    165. Compare Version Numbers
    258. Add Digits
  • 原文地址:https://www.cnblogs.com/ghhlyy/p/2942327.html
Copyright © 2011-2022 走看看