Asp.net mvc 3 用于EditorTemplate的嵌套模型的ASP.NET MVC3条件验证

Asp.net mvc 3 用于EditorTemplate的嵌套模型的ASP.NET MVC3条件验证,asp.net-mvc-3,validation,model,Asp.net Mvc 3,Validation,Model,假设您有一个viewModel: public class CreatePersonViewModel { [Required] public bool HasDeliveryAddress {get;set;} // Should only be validated when HasDeliveryAddress is true [RequiredIf("HasDeliveryAddress", true)] public Address Addres

假设您有一个viewModel:

public class CreatePersonViewModel
{
    [Required]
    public bool HasDeliveryAddress {get;set;}

    // Should only be validated when HasDeliveryAddress is true
    [RequiredIf("HasDeliveryAddress", true)]
    public Address Address { get; set; }
}
型号
地址
如下所示:

public class Address : IValidatableObject
{
    [Required]
    public string City { get; set; }
    [Required]        
    public string HouseNr { get; set; }
    [Required]
    public string CountryCode { get; set; }
    [Required]
    public string FirstName { get; set; }
    [Required]
    public string LastName { get; set; }
    [Required]
    public string ZipCode { get; set; }
    [Required]
    public string Street { get; set; }

    #region IValidatableObject Members

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        string[] requiredFields;
        var results = new List<ValidationResult>();

        // some custom validations here (I removed them to keep it simple)

        return results;
    }

    #endregion
}
公共类地址:IValidatableObject
{
[必需]
公共字符串City{get;set;}
[必需]
公共字符串HouseNr{get;set;}
[必需]
公共字符串CountryCode{get;set;}
[必需]
公共字符串名{get;set;}
[必需]
公共字符串LastName{get;set;}
[必需]
公共字符串ZipCode{get;set;}
[必需]
公共字符串Street{get;set;}
#表对象成员所在的区域
公共IEnumerable验证(ValidationContext ValidationContext)
{
字符串[]必填字段;
var results=新列表();
//这里有一些自定义验证(我删除了它们以保持简单)
返回结果;
}
#端区
}
有些人建议为Address创建一个viewmodel,并在其中添加一些自定义逻辑,但我需要一个
Address
的实例来传递给我的editor模板以获取Address

这里的主要问题是地址的验证是在我的PersonViewModel验证之前完成的,所以我无法阻止它


注意:RequiredIfAttribute是一个自定义属性,它正好满足我对简单类型的需求

西蒙·因斯(Simon Ince)的alpha版本似乎可以做你想做的事

更新
据我所知,“问题”在于类,它验证模型的基础是,如果它找到一个验证属性,它会询问该值是否有效(实际上相当合理!),它没有层次结构的概念。为了支持您所需的功能,您必须编写一个自定义模型绑定器,该绑定器根据您的声明性标记进行绑定,然后根据需要进行验证。

如果您确实编写了这样一个类,它可能是MVC futures的一个很好的候选者。

如果您使用了DataAnnotation或IValidatableObject,而不是在非常复杂的场景中限制验证能力的DataAnnotation或IValidatableObject,这将是一件轻而易举的事:

public class CreatePersonViewModelValidator : AbstractValidator<CreatePersonViewModel>
{
    public CreatePersonViewModelValidator()
    {
        RuleFor(x => x.Address)
            .SetValidator(new AddressValidator())
            .When(x => x.HasDeliveryAddress);
    }
}
公共类CreatePersonViewModelValidator:AbstractValidator
{
公共CreatePersonViewModelValidator()
{
规则(x=>x.Address)
.SetValidator(新的AddressValidator())
.When(x=>x.HasDeliveryAddress);
}
}

遗憾的是,他的RequiredIfAttribute只适用于简单类型,而不适用于复杂类型,如“我的地址”。我已经在使用他的RequiredIfAttribute了。@Peter更新了建议的解决方案,不幸的是,据我所知,这样的解决方案已经不存在了,所以你将有新的突破!我想说您的观察是正确的,不幸的是,我没有时间创建具有这种功能的自定义ModelBinder,更不用说彻底测试了。目前,FluentValidation似乎是一个更好的选择。我真的很想看到这样的东西在MVC的未来版本中实现。因为现在我觉得MVC在现实世界的应用程序中是缺乏的。我从来没有听说过这个库,但到目前为止我印象非常深刻。谢谢@Peter,我从ASP.NET MVC 1的第一个版本开始使用这个库。当我看到微软提供数据注释来执行验证时,我对自己说:WTF!!!与命令式验证相比,声明式验证的局限性要大得多。有些场景很难使用这些属性以声明方式表达。我的意思是,他们的工作非常好的东西,如要求,最小值,最大值。。。这正是互联网上充斥的东西,但一旦你开始编写真实世界的应用程序,你就会意识到它们的局限性。因此,只需
安装包FluentValidation.MVC3
,在你的
应用程序启动时添加以下行:
FluentValidationModelValidatorProvider.Configure(),摆脱所有的数据注释垃圾,开始为视图模型编写真正的验证器。这样做的另一个好处是验证逻辑与视图模型是分开的,并且可以是隔离的。您还可以根据HTTP参数对规则进行分组并有条件地应用它们,……我看到它与常规DataAnnotation完美集成。所以,现在,为了让同事们的学习曲线保持在一个较低的水平,我将只在复杂的验证中使用FluentValidation,并保留DataAnnotation所需的愚蠢的验证。