ManojAnavatti
ManojAnavatti

Reputation: 644

Get the parent object property value in child property in Validation Context

This question is related to Asp.net MVC5. Similar question is answer here: 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 w.r.t Effective date value in ParentModel.

Upvotes: 3

Views: 4971

Answers (3)

R. Schreurs
R. Schreurs

Reputation: 9065

As an alternative, you could move validation logic to the ParentModel by implementing IValidatableObject on it. 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.

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 w.r.t. the effective date, and a name property on ChildModel.)

Upvotes: 1

Dejan
Dejan

Reputation: 10323

The .NET DataAnnotations based validation does not offer recursive validation. However, you could extend it as explained here. Doing so, you gain control over how the ValidationContext (used for validating child objects) is created.

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.

Upvotes: 2

Mashton
Mashton

Reputation: 6415

You need to have a navigation property in your ChildModel class back to its parent. 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
}

Upvotes: 0

Related Questions