版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、最近在研究ASP.NET MVC 模型绑定,发现DefaultModelBinder 有一个弊端,就是无法实现对浏览器请求参数的自定义,最初的想法是想为实体模型的属性设置特性(Attribute),然后通过取得设置的特性值对属性进行赋值,研究了好久 MVC 源码之后发现可以通过重写DefaultModelBinder 的BindProperty 方法可以达到预期的目的。ASP.NET MVC 中有一个自定义模型绑定特性CustomModelBinderAttribute,打算通过重写CustomModelBinderAttribute来对实体属性进行出来,实现如下:AttributeUsage
2、Attribute(AttributeTargets.Class|AttributeTargets.Struct|AttributeTargets.Enum|AttributeTargets.Interface|AttributeTargets.Parameter, AllowMultiple = false,Inherited = false)public abstract class CustomModelBinderAttribute : Attribute但是由于CustomModelBinderAttribute 不支持对属性设置特性,所以只好继承Attribute 类重新写一个特性
3、,代码如下:/ / 表示一个调用自定义模型联编程序的特性。/ AttributeUsage(ValidTargets, AllowMultiple = false, Inherited = false)public class PropertyModelBinderAttribute : Attribute/ / 指定此属性可以应用特性的应用程序元素。/ internal const AttributeTargets ValidTargets = AttributeTargets.Field | AttributeTargets.Enum | AttributeTargets.Property
4、 | AttributeTargets.Parameter;/ / 声明属性名称。/ private string _propertyName = string.Empty;/ / 获取或设置属性别名。/ public string PropertyNameget return _propertyName; / / 使用指定的属性别名。/ / 指定的属性别名。public PropertyModelBinderAttribute(string propertyName)_propertyName = propertyName;/ / 检索关联的模型联编程序。/ / 对实现 System.Web
5、.Mvc.IModelBinder 接口的对象的引用。public IModelBinder GetBinder()return new PropertyModelBinder();这样就可以在实体模型的属性上设置别名了。/ / 表示一个城市筛选实体对象模型。/ ModelBinder(typeof(PropertyModelBinder)public class CityFilteringModel : BaseEntityModel/ / 获取或设置城市英文名称。/ public string CityEnglishName get; set; / / 获取或设置城市编号。/ Proper
6、tyModelBinder(cid)public int CityId get; set; / / 获取或设置城市名称。/ PropertyModelBinder(cname)public string CityName get; set; 最后听过重写DefaultModelBinder 的BindProperty 和SetProperty 方法就可以对模型绑定的属性实现自定义了。/ / 将浏览器请求映射到数据对象。/ public class PropertyModelBinder : DefaultModelBinder/ / 初始化 类的新实例。/ public PropertyMod
7、elBinder()/ / 使用指定的控制器上下文和绑定上下文来绑定模型。/ / 运行控制器的上下文。/ 绑定模型的上下文。/ 已绑定的对象。public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)var model = base.BindModel(controllerContext, bindingContext);if (model is BaseEntiryModel) (BaseEntiryModel)model).BindMode
8、l(controllerContext, bindingContext);return model;/ / 使用指定的控制器上下文、绑定上下文、属性描述符和属性联编程序来返回属性值。/ / 运行控制器的上下文。/ 绑定模型的上下文。/ 要访问的属性的描述符。/ 一个对象,提供用于绑定属性的方式。/ 一个对象,表示属性值。protected override object GetPropertyValue(ControllerContext controllerContext, ModelBindingContext bindingContext, System.ComponentModel.P
9、ropertyDescriptor propertyDescriptor, IModelBinder propertyBinder)var value = base.GetPropertyValue(controllerContext, bindingContext, propertyDescriptor, propertyBinder);return value;/ / 使用指定的控制器上下文、绑定上下文和指定的属性描述符来绑定指定的属性。/ / 运行控制器的上下文。/ 绑定模型的上下文。/ 描述要绑定的属性。protected override void BindProperty(Cont
10、rollerContext controllerContext, ModelBindingContext bindingContext, PropertyDescriptor propertyDescriptor)string fullPropertyKey = CreateSubPropertyName(bindingContext.ModelName, propertyDescriptor.Name);object propertyValue = null;if (propertyDescriptor.Attributestypeof(PropertyModelBinderAttribut
11、e) != null)var attribute = (PropertyModelBinderAttribute)propertyDescriptor.Attributestypeof(PropertyModelBinderAttribute);string propertyName = attribute.PropertyName;var valueResult = bindingContext.ValueProvider.GetValue(propertyName);if (valueResult != null)propertyValue = valueResult.AttemptedV
12、alue;elseif (!bindingContext.ValueProvider.ContainsPrefix(fullPropertyKey)return;/ call into the propertys model binderIModelBinder propertyBinder = Binders.GetBinder(propertyDescriptor.PropertyType);object originalPropertyValue = propertyDescriptor.GetValue(bindingContext.Model);ModelMetadata prope
13、rtyMetadata = bindingContext.PropertyMetadatapropertyDescriptor.Name;propertyMetadata.Model = originalPropertyValue;ModelBindingContext innerBindingContext = new ModelBindingContext()ModelMetadata = propertyMetadata,ModelName = fullPropertyKey,ModelState = bindingContext.ModelState,ValueProvider = b
14、indingContext.ValueProvider;object newPropertyValue = GetPropertyValue(controllerContext, innerBindingContext, propertyDescriptor, propertyBinder);if (newPropertyValue = null)newPropertyValue = propertyValue;propertyMetadata.Model = newPropertyValue;/ validationModelState modelState = bindingContext
15、.ModelStatefullPropertyKey;if (modelState = null | modelState.Errors.Count = 0)if (OnPropertyValidating(controllerContext, bindingContext, propertyDescriptor, newPropertyValue)SetProperty(controllerContext, bindingContext, propertyDescriptor, newPropertyValue);OnPropertyValidated(controllerContext,
16、bindingContext, propertyDescriptor, newPropertyValue);elseSetProperty(controllerContext, bindingContext, propertyDescriptor, newPropertyValue);/ Convert FormatExceptions (type conversion failures) into InvalidValue messagesforeach (ModelError error in modelState.Errors.Where(err = String.IsNullOrEmp
17、ty(err.ErrorMessage) & err.Exception != null).ToList()for (Exception exception = error.Exception; exception != null; exception = exception.InnerException)/ We only consider known type of exception and do not make too aggressive changes hereif (exception is FormatException | exception is OverflowExce
18、ption)string displayName = propertyMetadata.GetDisplayName();string errorMessageTemplate = GetValueInvalidResource(controllerContext);string errorMessage = String.Format(CultureInfo.CurrentCulture, errorMessageTemplate, modelState.Value.AttemptedValue, displayName);modelState.Errors.Remove(error);mo
19、delState.Errors.Add(errorMessage);break;/base.BindProperty(controllerContext, bindingContext, propertyDescriptor);/ / 使用指定的控制器上下文、绑定上下文和属性值来设置指定的属性。/ / 运行控制器的上下文。/ 绑定模型的上下文。/ 描述要绑定的属性。/ 为属性设置的值。protected override void SetProperty(ControllerContext controllerContext, ModelBindingContext bindingContex
20、t, PropertyDescriptor propertyDescriptor, object value)ModelMetadata propertyMetadata = bindingContext.PropertyMetadatapropertyDescriptor.Name;propertyMetadata.Model = value;string modelStateKey = CreateSubPropertyName(bindingContext.ModelName, propertyMetadata.PropertyName);if (value = null & bindi
21、ngContext.ModelState.IsValidField(modelStateKey)ModelValidator requiredValidator = ModelValidatorProviders.Providers.GetValidators(propertyMetadata, controllerContext).Where(v = v.IsRequired).FirstOrDefault();if (requiredValidator != null)foreach (ModelValidationResult validationResult in requiredVa
22、lidator.Validate(bindingContext.Model)bindingContext.ModelState.AddModelError(modelStateKey, validationResult.Message);bool isNullValueOnNonNullableType = value = null & !TypeAllowsNullValue(propertyDescriptor.PropertyType);if (!propertyDescriptor.IsReadOnly & !isNullValueOnNonNullableType)tryvar ty
23、peValue = Convert.ChangeType(value, propertyDescriptor.PropertyType, CultureInfo.InvariantCulture);propertyDescriptor.SetValue(bindingContext.Model, typeValue);catch (Exception ex)if (bindingContext.ModelState.IsValidField(modelStateKey)bindingContext.ModelState.AddModelError(modelStateKey, ex);if (
24、isNullValueOnNonNullableType & bindingContext.ModelState.IsValidField(modelStateKey)bindingContext.ModelState.AddModelError(modelStateKey, GetValueRequiredResource(controllerContext);/ / 使用指定的控制器上下文和绑定上下文来返回模型的属性。/ / 运行控制器的上下文。/ 绑定模型的上下文。/ 属性描述符的集合。protected override PropertyDescriptorCollection Get
25、ModelProperties(ControllerContext controllerContext, ModelBindingContext bindingContext)bindingContext.PropertyFilter = new Predicate(pred);var values = base.GetModelProperties(controllerContext, bindingContext);return values;/ / 获取属性筛选器的判定对象。/ / 属性筛选器的属性。/ 一个布尔值。protected bool pred(string target)re
26、turn true;#region Private ./ / 类型允许空值。/ / 指定的类型。/ 若类型值为空,则返回 true,否则返回 false。private static bool TypeAllowsNullValue(Type type)return (!type.IsValueType | IsNullableValueType(type);/ / 是可为空值类型。/ / 指定的类型。/ 若类型值为空,则返回 true,否则返回 false。private static bool IsNullableValueType(Type type)return Nullable.GetUnderlyingType(type) != null;/ / 获取价值无效的资源。/ / / private static string GetValueInvalidResource(ControllerContext controllerCont
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025至2030年中国自粘PVC单色贴数据监测研究报告
- 2025至2030年中国建筑围挡板数据监测研究报告
- 2025至2030年中国多功能全定量金标检测仪数据监测研究报告
- 2025年中国鲫鱼料市场调查研究报告
- 2025至2031年中国肖像刻瓷行业投资前景及策略咨询研究报告
- 二零二五版女方离婚子女抚养费支付合同3篇
- 2025年度面粉加工厂与粮食银行面粉质押融资合同4篇
- 2024-2030年中国消炎止痛药行业市场调查研究及投资潜力预测报告
- 2025年度房地产大数据市场研究合同4篇
- 二零二五年度养殖场养殖品种改良承包服务合同样本4篇
- 南通市2025届高三第一次调研测试(一模)地理试卷(含答案 )
- 2025年上海市闵行区中考数学一模试卷
- 2025中国人民保险集团校园招聘高频重点提升(共500题)附带答案详解
- 重症患者家属沟通管理制度
- 法规解读丨2024新版《突发事件应对法》及其应用案例
- IF钢物理冶金原理与关键工艺技术1
- 销售提成对赌协议书范本 3篇
- 劳务派遣招标文件范本
- EPC项目阶段划分及工作结构分解方案
- 信息安全意识培训课件
- 金字塔原理完整版本
评论
0/150
提交评论