您的位置:首页 > 其它

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

2013-03-04 23:41 267 查看
在之前的文章中我们讲过,在获取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(***);

}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: