




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、最近在研究 ASP.NET MVC 模型绑定,发现 DefaultModelBinder 有一个弊端,就是无法实现对浏览器请求参数的自定义,最初的想法是想为实体模型的属性设置特性(Attribute),然后通过取得设置的特性值对属性进行赋值,研究了好久 MVC 源码之后发现可以通过重写 DefaultModelBinder 的 BindProperty 方法可以达到预期的目的。ASP.NET MVC 中有一个自定义模型绑定特性 CustomModelBinderAttribute,打算通过重写 CustomModelBinderAtt
2、ribute 来对实体属性进行出来,实现如下:AttributeUsageAttribute(AttributeTargets.Class|AttributeTargets.Struct|AttributeTargets.Enum|AttributeTargets.Interface|AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)public abstract class CustomModelBinderAttribute : Attribute
3、但是由于 CustomModelBinderAttribute 不支持对属性设置特性,所以只好继承 Attribute 类重新写一个特性,代码如下:/ <summary>/ 表示一个调用自定义模型联编程序的特性。/ </summary>AttributeUsage(ValidTargets, AllowMultiple = false, Inherited = false)public class PropertyModelBinderAttribute : Attribute / <summary
4、> / 指定此属性可以应用特性的应用程序元素。 / </summary> internal const AttributeTargets ValidTargets = AttributeTargets.Field | AttributeTargets.Enum | AttributeTargets.Property | AttributeTargets.Parameter; / <summ
5、ary> / 声明属性名称。 / </summary> private string _propertyName = string.Empty; / <summary> / 获取或设置属性别名。 / </summary> p
6、ublic string PropertyName get return _propertyName; / <summary> / 使用指定的属性别名。 / </summary> / &l
7、t;param name="propertyName">指定的属性别名。</param> public PropertyModelBinderAttribute(string propertyName) _propertyName = propertyName; /
8、<summary> / 检索关联的模型联编程序。 / </summary> / <returns>对实现 System.Web.Mvc.IModelBinder 接口的对象的引用。</returns> public IModelBinder GetBinder()
9、0; return new PropertyModelBinder(); 这样就可以在实体模型的属性上设置别名了。/ <summary>/ 表示一个城市筛选实体对象模型。/ </summary>ModelBinder(typeof(PropertyModelBinder)public class CityFilteringModel : BaseEntityModel / <summary>
10、0; / 获取或设置城市英文名称。 / </summary> public string CityEnglishName get; set; / <summary> / 获取或设置城市编号。 / </summary> PropertyModelBinder("cid
11、") public int CityId get; set; / <summary> / 获取或设置城市名称。 / </summary> PropertyModelBinder("cname") public string CityName get; set; 最后听
12、过重写 DefaultModelBinder 的 BindProperty 和 SetProperty 方法就可以对模型绑定的属性实现自定义了。/ <summary>/ 将浏览器请求映射到数据对象。/ </summary>public class PropertyModelBinder : DefaultModelBinder / <summary> / 初始化 <see cref="PropertyModel
13、Binder"/> 类的新实例。 / </summary> public PropertyModelBinder() / <summary> / 使用指定的控制器上下文和绑定上下文来绑定模型。 / </summary
14、> / <param name="controllerContext">运行控制器的上下文。</param> / <param name="bindingContext">绑定模型的上下文。</param> / <returns>已绑定的对象。</returns> public override
15、object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) var model = base.BindModel(controllerContext, bindingContext); if (model is BaseEntiryModel)
16、 (BaseEntiryModel)model).BindModel(controllerContext, bindingContext); return model; / <summary> / 使用指定的控制器上下文、绑定上下文、属性描述符和属性联编程序来返回属性值。 / <
17、;/summary> / <param name="controllerContext">运行控制器的上下文。</param> / <param name="bindingContext">绑定模型的上下文。</param> / <param name="propertyDescriptor">要访问的属性的描述符。</para
18、m> / <param name="propertyBinder">一个对象,提供用于绑定属性的方式。</param> / <returns>一个对象,表示属性值。</returns> protected override object GetPropertyValue(ControllerContext controllerContext, ModelBindingContext b
19、indingContext, System.ComponentModel.PropertyDescriptor propertyDescriptor, IModelBinder propertyBinder) var value = base.GetPropertyValue(controllerContext, bindingContext, propertyDescriptor, propertyBinder); &
20、#160; return value; / <summary> / 使用指定的控制器上下文、绑定上下文和指定的属性描述符来绑定指定的属性。 / </summary> / <param name="controllerContext">运行控制
21、器的上下文。</param> / <param name="bindingContext">绑定模型的上下文。</param> / <param name="propertyDescriptor">描述要绑定的属性。</param> protected override void BindProperty(ControllerContext controlle
22、rContext, ModelBindingContext bindingContext, PropertyDescriptor propertyDescriptor) string fullPropertyKey = CreateSubPropertyName(bindingContext.ModelName, propertyDescriptor.Name);
23、0;object propertyValue = null; if (propertyDescriptor.Attributestypeof(PropertyModelBinderAttribute) != null) var attribute = (P
24、ropertyModelBinderAttribute)propertyDescriptor.Attributestypeof(PropertyModelBinderAttribute); string propertyName = attribute.PropertyName; var valueResult =
25、 bindingContext.ValueProvider.GetValue(propertyName); if (valueResult != null) propertyValue = valueResult.AttemptedValue;
26、 else if (!bindingContext.ValueProvider.ContainsPrefix(fullPropertyKey)
27、60; return;
28、160; / call into the property's model binder IModelBinder propertyBinder = Binders.GetBinder(propertyDescriptor.PropertyType); object originalPropertyValue = propertyDescriptor.Ge
29、tValue(bindingContext.Model); ModelMetadata propertyMetadata = bindingContext.PropertyMetadatapropertyDescriptor.Name; propertyMetadata.Model = originalPropertyValue;
30、0; ModelBindingContext innerBindingContext = new ModelBindingContext() ModelMetadata = propertyMetadata,
31、ModelName = fullPropertyKey, ModelState = bindingContext.ModelState, ValueProvider = bindingContext.ValueProvider
32、60; object newPropertyValue = GetPropertyValue(controllerContext, innerBindingContext, propertyDescriptor, propertyBinder); if (newPropertyValue = null)
33、 newPropertyValue = propertyValue; propertyMetadata.Model = newPropertyValue; / validat
34、ion ModelState modelState = bindingContext.ModelStatefullPropertyKey; if (modelState = null | modelState.Errors.Count = 0)
35、 if (OnPropertyValidating(controllerContext, bindingContext, propertyDescriptor, newPropertyValue)
36、; SetProperty(controllerContext, bindingContext, propertyDescriptor, newPropertyValue); OnPropertyValidated(controllerContext, bindingContext, propertyDescriptor, newPropertyValue); &
37、#160; else SetProperty(controllerConte
38、xt, bindingContext, propertyDescriptor, newPropertyValue); / Convert FormatExceptions (type conversion failures) into InvalidValue messages foreach (Mod
39、elError error in modelState.Errors.Where(err => String.IsNullOrEmpty(err.ErrorMessage) && err.Exception != null).ToList()
40、for (Exception exception = error.Exception; exception != null; exception = exception.InnerException)
41、160; / We only consider "known" type of exception and do not make too aggressive changes here if (exception is FormatException | exception is OverflowException)
42、 string displayName = propertyMetadat
43、a.GetDisplayName(); string errorMessageTemplate = GetValueInvalidResource(controllerContext);
44、0; string errorMessage = String.Format(CultureInfo.CurrentCulture, errorMessageTemplate, modelState.Value.AttemptedValue, displayName);
45、0; modelState.Errors.Remove(error); modelState.Errors.Add(errorMessage);
46、160; break;
47、160; /base.BindProperty(controllerContext, bindingContext, propertyDescriptor);
48、 / <summary> / 使用指定的控制器上下文、绑定上下文和属性值来设置指定的属性。 / </summary> / <param name="controllerContext">运行控制器的上下文。</param> / <param name="bindingCon
49、text">绑定模型的上下文。</param> / <param name="propertyDescriptor">描述要绑定的属性。</param> / <param name="value">为属性设置的值。</param> protected override void SetProperty(ControllerContext con
50、trollerContext, ModelBindingContext bindingContext, PropertyDescriptor propertyDescriptor, object value) ModelMetadata propertyMetadata = bindingContext.PropertyMetadatapropertyDescriptor.Name;
51、 propertyMetadata.Model = value; string modelStateKey = CreateSubPropertyName(bindingContext.ModelName, propertyMetadata.PropertyName); if (value = null && bindingContext.ModelState
52、.IsValidField(modelStateKey) ModelValidator requiredValidator = ModelValidatorProviders.Providers.GetValidators(propertyMetadata, controllerContext).Where(v => v.IsRequired).Firs
53、tOrDefault(); if (requiredValidator != null) foreach (ModelVal
54、idationResult validationResult in requiredValidator.Validate(bindingContext.Model) bi
55、ndingContext.ModelState.AddModelError(modelStateKey, validationResult.Message);
56、; bool isNullValueOnNonNullableType = value = null && !TypeAllowsNullValue(propertyDescriptor.PropertyType); if (!propertyDescriptor.IsReadOnly && !isNullValueOnNonNullableType) &
57、#160; try var typeValue =
58、Convert.ChangeType(value, propertyDescriptor.PropertyType, CultureInfo.InvariantCulture); propertyDescriptor.SetValue(bindingContext.Model, typeValue);
59、 catch (Exception ex) if (bindingContext.Mod
60、elState.IsValidField(modelStateKey) bindingContext.ModelState.AddModelError(modelStat
61、eKey, ex); if (isNullValueOnNon
62、NullableType && bindingContext.ModelState.IsValidField(modelStateKey) bindingContext.ModelState.AddModelError(modelStateKey, GetValueRequiredResource(controllerContext);
63、0; / <summary> / 使用指定的控制器上下文和绑定上下文来返回模型的属性。 / </summary> / <param name="controllerContext">运行控制器
64、的上下文。</param> / <param name="bindingContext">绑定模型的上下文。</param> / <returns>属性描述符的集合。</returns> protected override PropertyDescriptorCollection GetModelProperties(ControllerContext controllerCo
65、ntext, ModelBindingContext bindingContext) bindingContext.PropertyFilter = new Predicate<string>(pred); var values = base.GetModelProperties(controllerContext, bindingContext);
66、 return values; / <summary> / 获取属性筛选器的判定对象。 / </summary> / <param name="target">属性筛选器的属性。</param>
67、 / <returns>一个布尔值。</returns> protected bool pred(string target) return true; #region Private .
68、 / <summary> / 类型允许空值。 / </summary> / <param name="type">指定的类型。</param> / <returns>若类型值为空,则返回 true,否则返回 false。</returns> private stati
69、c bool TypeAllowsNullValue(Type type) return (!type.IsValueType | IsNullableValueType(type); / <summary> / 是可为空值类型。 / </s
70、ummary> / <param name="type">指定的类型。</param> / <returns>若类型值为空,则返回 true,否则返回 false。</returns> private static bool IsNullableValueType(Type type)
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 关注信息处理技术员考试试题
- 材料力学与智能材料性能监测重点基础知识点
- 材料疲劳裂纹萌生机理研究重点基础知识点
- 检修火灾应急演练预案(3篇)
- 化验室初期火灾应急预案(3篇)
- 经济政策与社会治理的良性互动试题及答案
- 高考数学整体复习安排与试题及答案
- 边防火灾应急预案(3篇)
- 地铁区间火灾的应急预案(3篇)
- 解决代数难题的思路试题及答案
- 血常规报告单
- JJG 443-2023燃油加油机(试行)
- 国家开放大学-传感器与测试技术实验报告(实验成绩)
- 机械工业出版社2020《人工智能导论》课程第1章 绪论
- 教育教学实习教案幼儿园
- 大众电子助力转向EPS 双齿轮电动助力转向系统
- 【医院管理案例学习】-床单位终末消毒标准的执行
- 退化草地修复亲水性聚氨酯复合材料应用技术规范
- 暗挖格栅加工技术交底
- DB5106∕T 01-2019 农村彩钢棚管理指南
- 2023年安徽省公安机关警务辅助人员条例训练题库211题及答案
评论
0/150
提交评论