.NETMVC的自定义模型属性别名绑定的使用讲解_第1页
.NETMVC的自定义模型属性别名绑定的使用讲解_第2页
.NETMVC的自定义模型属性别名绑定的使用讲解_第3页
.NETMVC的自定义模型属性别名绑定的使用讲解_第4页
.NETMVC的自定义模型属性别名绑定的使用讲解_第5页
已阅读5页,还剩4页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

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. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论