为什么ASP.NET MVC在数据绑定期间关心我的只读属性?

Sim*_*ver 21 asp.net-mvc modelbinders asp.net-mvc-2

编辑:添加了赏金,因为我正在寻找除此之外的MVC3解决方案(如果存在):

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[] {','});
        }
    }
Run Code Online (Sandbox Code Playgroud)

这是我的模型的一部分,所以它受到约束.在ASP.NET MVC2 RC2之前,此字段在数据绑定期间从未引起过问题.我从来没有真正想过它 - 毕竟它只是只读.

现在虽然在2010年1月的RC2版本中,它在数据绑定期间给出了一个错误 - 因为默认模型绑定器似乎想要检查此值(即使它是只读的).

它是'base.OnModelUpdated'行导致触发此错误.

public class AddressModelBinder : DefaultModelBinder
{
    protected override void OnModelUpdated(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        base.OnModelUpdated(controllerContext, bindingContext);
Run Code Online (Sandbox Code Playgroud)

最后几分钟对模型绑定器的更改显然导致了行为的这种变化 - 但我还不确定它的重现是什么 - 或者这是否是一个错误?我正在将此传递给MVC团队,但好奇是否有人在此期间有任何建议我如何阻止此属性绑定.

这篇文章非常值得一读 - 但是根本没有提到readonly属性(不是我期望的).问题(如果有的话)可能比这种情况更广泛 - 我只是不确定是否有任何反复 - 如果有的话!

ASP.NET MVC中的输入验证与模型验证


根据@haacked的要求,这里是堆栈跟踪:

我通过简单地将以下行添加到ANY模型并为相应的操作方法发布帖子来实现此目的.在这个例子中,我将它添加到我最简单的模型中.

 public string Foo { get { throw new Exception("bar"); } }
Run Code Online (Sandbox Code Playgroud)

[TargetInvocationException:对象'Rolling_Razor_MVC.Models.ContactUsModel'上的属性访问者'Foo'引发了以下异常:'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(Con trollerContext 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型号)+73

Rud*_*udy 18

我相信我遇到了类似的问题.我发布了详细信息:

http://forums.asp.net/t/1523362.aspx


编辑:MVC团队的回复(来自上面的URL):

我们对此进行了调查,并得出结论认证系统的行为符合预期.由于模型验证涉及尝试对所有属性运行验证,并且由于非可空值类型属性具有隐式[Required]属性,因此我们将验证此属性并在此过程中调用其getter.我们知道这是对产品V1的重大改变,但有必要使新模型验证系统正常运行.

你有几个选择来解决这个问题.其中任何一个应该工作:

  • 将Date属性更改为方法而不是属性; 这样,它将被MVC框架忽略.
  • 将属性类型更改为DateTime?而不是DateTime.这将从此属性中删除隐式[必需].
  • 清除静态DataAnnotationsModelValidatorProvider.AddImplicitRequiredAttributeForValueTypes标志.这将从应用程序范围内的所有非可空值类型属性中删除隐式[必需].我们正在考虑在产品的V3中添加一个属性,该属性将向我们发出信号"不绑定它,不验证它,只是假装这个属性不存在".

再次感谢您的报告!