DataAnnotationsModelValidatorProvider.AddImplicitrequiredAttributeForValueTypes = false;
我的“地址”模型“CityStateZip”上有一个只读属性。
这是从美国地址获取城市,州,邮政编码的便捷方式。如果国家不是美国,则会引发异常(呼叫者应先检查)。
public string CityStateZip { get { if (IsUSA == false) { throw new ApplicationException("CityStateZip not valid for international addresses!"); } return (City + "," + StateCd + " " + ZipOrPostal).Trim().Trim(new char[] {','}); } }
这是我的模型的一部分,所以它受到约束。在ASP.NET MVC2 RC2之前,该字段在数据绑定期间从未引起问题。我从来没有想过它 – 毕竟只是只读。
现在虽然2010年1月RC2版本在数据绑定中给我一个错误 – 因为默认模型binder似乎想要检查这个值(即使它是只读的)。
它是’base.OnModelUpdated’行,导致此错误被触发。
public class AddressModelBinder : DefaultModelBinder { protected override void OnModelUpdated(ControllerContext controllerContext,ModelBindingContext bindingContext) { base.OnModelUpdated(controllerContext,bindingContext);
模型绑定的最后几分钟更改明显地导致了行为的这种变化 – 但是我不太清楚它的后果是什么 – 或者这是否是一个错误?我把这个传递给了MVC团队,但好奇的是,如果其他人有任何建议,同时我如何可以防止这个属性绑定。
这篇文章非常值得阅读有关这些变化 – 但是根本没有提到只读属性(不是我期望的)。这个问题(如果有的话)可能比这种情况更广泛 – 我不知道有什么后果 – 如果有的话!
Input Validation vs. Model Validation in ASP.NET MVC
根据@haacked的要求,这里是stacktrace:
我通过简单地将以下行添加到任何模型,并发布到相应的操作方法。在这种情况下,我把它添加到我最简单的模型中。
public string Foo { get { throw new Exception("bar"); } }
[TargetInvocationException: Property accessor ‘Foo’ on object ‘Rolling_Razor_MVC.Models.ContactUsModel’ threw the following exception:’bar’]
System.ComponentModel.ReflectPropertyDescriptor.GetValue(Object component) +390
System.Web.Mvc.<>c__DisplayClassb.<GetPropertyValueAccessor>b__a() +18
System.Web.Mvc.ModelMetadata.get_Model() +22
System.Web.Mvc.ModelMetadata.get_RealModelType() +29
System.Web.Mvc.<GetValidatorsImpl>d__0.MoveNext() +38
System.Linq.<SelectManyIterator>d__14`2.MoveNext() +273
System.Web.Mvc.<Validate>d__5.MoveNext() +644
System.Web.Mvc.DefaultModelBinder.OnModelUpdated(ControllerContext controllerContext,ModelBindingContext bindingContext) +92
System.Web.Mvc.DefaultModelBinder.BindComplexElementalModel(ControllerContext controllerContext,ModelBindingContext bindingContext,Object model) +60
System.Web.Mvc.DefaultModelBinder.BindComplexModel(ControllerContext controllerContext,ModelBindingContext bindingContext) +1048
System.Web.Mvc.DefaultModelBinder.BindModel(ControllerContext controllerContext,ModelBindingContext bindingContext) +280
System.Web.Mvc.Controller.TryUpdateModel(TModel model,String prefix,String[] includeProperties,String[] excludeProperties,IValueProvider valueProvider) +449
System.Web.Mvc.Controller.TryUpdateModel(TModel model) +73
解决方法
http://forums.asp.net/t/1523362.aspx
编辑:MVC团队的响应(来自URL):
我们调查了这一点,并得出结论,验证系统的行为是按预期的。由于模型验证涉及尝试在所有属性上运行验证,并且由于非可空值类型属性具有隐式[必需]属性,因此我们将在该过程中验证此属性并调用其getter。我们了解到,这是从V1产品的突破性变化,但是必须使新型号验证系统正常运行。
你有几个选择可以解决这个问题。其中任何一个应该工作:
>将Date属性更改为方法而不是属性;这样就可以被MVC框架忽略了。
>将属性类型更改为DateTime?而不是DateTime。这将从此属性中删除隐式[必需]。
>清除静态DataAnnotationsModelValidatorProvider.AddImplicitrequiredAttributeForValueTypes标志。这从应用程序范围内的所有非可空值类型属性中移除隐式[必需]。
我们正在考虑在V3中添加一个属性,该信号将向我们发出信号,“不要绑定它,不要验证它,只是假装该属性不存在”。
再次感谢报告!