【问题标题】:Prevention of validating all of the properties of inner object in MVC防止验证 MVC 中内部对象的所有属性
【发布时间】:2010-11-22 14:50:31
【问题描述】:

例如我有

public class Person
{
    public int Id {get;set;}
    [Required()]
    public string Name {get;set;}
    [Required()]
    public Address Address {get;set;}
}

public class Address
{
    public int Id {get;set;}
    [Required()]
    public string City {get;set;}
    [Required()]
    public string Street {get;set;}
}

我需要验证 Address 中的每个属性,但是在验证 Person 时,我只需要验证 Address 的 id。 怎么做??

【问题讨论】:

    标签: asp.net-mvc asp.net-mvc-2 validation


    【解决方案1】:

    我不知道你的意思是什么我需要验证 Address 中的每个属性,但是在验证 Person 时我只需要验证 Address 的 id。如果我错了,请纠正我,但我是这样理解您的问题的:您有两个不同的控制器操作:

    [HttpPost]
    public ActionResult ValidateAddress(Address address)
    {
        ... // validate all properties of address
    }
    
    [HttpPost]
    public ActionResult ValidatePerson(Person person)
    {
        ... // validate only the Id of a person's Address
    }
    

    我个人会使用FluentValidation 而不是数据注释,因为它可以让您以更简洁的方式表达您的验证逻辑,并且可以处理像这样的案例。下面是如何以一种优雅的方式表达这一点:

    /// <summary>
    /// Validates all properties of an address
    /// </summary>
    public class AddressValidator : AbstractValidator<Address>
    {
        public AddressValidator()
        {
            RuleFor(x => x.Id).NotEmpty();
            RuleFor(x => x.City).NotEmpty();
            RuleFor(x => x.Street).NotEmpty();
        }
    }
    
    /// <summary>
    /// Validates only the id of an address
    /// </summary>
    public class PersonAddressValidator : AbstractValidator<Address>
    {
        public PersonAddressValidator()
        {
            RuleFor(x => x.Id).NotEmpty();
        }
    }
    
    /// <summary>
    /// Validates a Person
    /// </summary>
    public class PersonValidator : AbstractValidator<Person>
    {
        public PersonValidator()
        {
            RuleFor(x => x.Name).NotEmpty();
            RuleFor(x => x.Address).SetValidator(new PersonAddressValidator());
        }
    }
    

    您的视图模型类变得简单:

    [Validator(typeof(PersonValidator))]
    public class Person
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public Address Address { get; set; }
    }
    
    [Validator(typeof(AddressValidator))]
    public class Address
    {
        public int Id { get; set; }
        public string City { get; set; }
        public string Street { get; set; }
    }
    

    并且您的控制器操作保持不变,只是它们现在按预期运行。

    【讨论】:

    • 请允许我强烈推荐这个答案。我尝试使用 DataAnnotions 来做同样的事情(表单最多可以占用 3 个 X 类型,第一个是必需的,其他 2 个是可选的)并且永远无法超过可选对象的必需属性。我最终转向跳过默认验证并为该表单编写自己的验证。
    • 非常感谢,这非常有用,但是有没有办法在不修改模型的情况下做到这一点(我更喜欢 POCO 模型)(我可以将验证器附加到没有这个(验证器)属性的类)。
    • 是的,您可以使用 POCO 执行此操作。您需要编写一个自定义验证器工厂(实现IValidatorFactory 接口)并在您的 Application_Start 中使用此自定义工厂而不是默认工厂(使用属性)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多