简体   繁体   English

在验证上下文中获取子属性中的父对象属性值

[英]Get the parent object property value in child property in Validation Context

This question is related to Asp.net MVC5. 此问题与Asp.net MVC5有关。 Similar question is answer here : https://stackoverflow.com/questions/7674841/net-mvc3-conditionally-validating-property-which-relies-on-parent-object-proper 类似的问题在这里回答:https://stackoverflow.com/questions/7674841/net-mvc3-conditionally-validating-property-which-relies-on-parent-object-proper

I have the following View Model: 我有以下视图模型:

public class ParentModel
{
    public DateTime EffectiveDate { get; set; }
    public List<ChildModel> Children { get; set; }
    //.....
    //.....
}
public class ChildModel
{
    [DateOfBirthRange(ErrorMessage = "Date of Birth must be within range")]
    public DateTime DateOfBirth { get; set; }
    //.....
    //.....
}

public class DateOfBirthRange : ValidationAttribute
{
    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        return null;
        //here validationContext.ObjectInstance is ChildModel
        //How do i get the Effective Date of ParentModel?
    }
}

ChildModel is a list and I need to validate for DateOfBith of all child models wrt Effective date value in ParentModel. ChildModel是一个列表,我需要验证所有子模型的DateOfBith,并注明ParentModel中的有效日期值。

You need to have a navigation property in your ChildModel class back to its parent. 您需要在ChildModel类中拥有一个导航属性,使其返回其父级。 Then you can do something like the following: 然后,您可以执行以下操作:

public override ValidationResult(object value, ValidationContext validationContext)
{
    var childModel= validationContext.ObjectInstance as ChildModel;
    var effectiveDate  = childModel.Parent.EffectiveDate;
    // do your tests against effectiveDate and childModel date
}

The .NET DataAnnotations based validation does not offer recursive validation. 基于.NET DataAnnotations的验证不提供递归验证。 However, you could extend it as explained here . 但是,您可以按照此处的说明进行扩展。 Doing so, you gain control over how the ValidationContext (used for validating child objects) is created. 这样,您就可以控制如何创建ValidationContext (用于验证子对象)。

So, in the ValidateObjectAttribute of the mentioned article, when instantiating the new ValidationContext in IsValid , instead of passing null as a service provider, you could pass a custom IServiceProvider that gives you the parent validation context and using its ObjectInstance you get the parent object being validated. 因此,在上述文章的ValidateObjectAttribute中,当在IsValid实例化新的ValidationContext时,可以通过自定义IServiceProvider来提供父验证上下文,并使用其ObjectInstance来传递父对象,而不是将null作为服务提供者传递已验证。

As an alternative, you could move validation logic to the ParentModel by implementing IValidatableObject on it. 或者,可以通过在其上实现IValidatableObject将验证逻辑移至ParentModel。 Arguably, your rule does not apply to the ChildModels themselves, but to the the complete Parent object with all its children, as the effective date is a property of the parent object. 可以说,您的规则不适用于ChildModels本身,而是适用于带有所有子项的完整的Parent对象,因为生效日期是父对象的属性。

public class ParentModel : IValidatableObject
{
    //.....
    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        var result = new List<ValidationResult>();
        foreach (var child in Children.Where(child => child.DateOfBirth.Date < EffectiveDate.AddYears(-1).Date || child.DateOfBirth.Date > EffectiveDate.Date))
        {
            result.Add(new ValidationResult($"The date of birth {child.DateOfBirth} of child {child.Name} is not between now and a year ago."));
        }

        return result;
    }
}

(assuming a rule for validity of date of birth wrt the effective date, and a name property on ChildModel.) (假设有生效日期和生效日期的规则,以及ChildModel上的name属性。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM