3

I have an View Model that is an IValidatableObject that contains a collection of CustomFields that are also IValidatableObject. Both the view model and the custom fields have custom logic to check if they are valid when posted.

The View Model looks like this:

public class ViewModel : IValidatableObject
{
    public bool IsInspected { get; set; }
    public DateTime? InspectedDate { get; set; }
    public IList<CustomField> CustomFields { get; set; }

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        if (IsInspected == true && InspectedDate == null)
        {
            yield return new ValidationResult("Inspection Date is required if Inspected.", new[] { nameof(InspectedDate) });
        }
    }
}

public class CustomField : IValidatableObject
{
    public bool IsRequired { get; set; }
    public string Value { get; set; }
    public string DisplayName { get; set; }

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        if (IsRequired && string.IsNullOrWhiteSpace(Value))
        {
            yield return new ValidationResult($"The {DisplayName} field is required.", new[] { nameof(Value) });
        }
    }
}

This correctly validates the CustomFields, but it doesn't validate the ViewModel itself unless the CustomFields have no errors. This means if the user posts invalid Custom Fields and invalid View Model fields, they aren't given notification of the View Model fields until they correct the Custom Fields, post again, and then get the View Model fields validated.

I tried removing IValidatableObject from CustomField and instead doing a foreach loop inside the ViewModel.Validate() method, but that didn't correctly assign ModelState Keys that highlight the input fields on the form. For example the method shown above creates a ModelState Key of CustomFields[0].Value while doing a loop inside ViewModel just creates a Key of Value.

Valuator
  • 3,262
  • 2
  • 29
  • 53
  • That is by design. What you should be doing is using validation attributes applied to your view model properties, which also has the added benefit of giving you client side validation as well –  Aug 03 '18 at 02:33
  • 1
    @StephenMuecke Declarative (attribute-based) validation is not expressive enough for scenarios like the OP's. There is currently no way to express the OP's required validation logic using only built-in attributes and writing a new custom validation attribute for each scenario is not ideal either. – Dai Nov 24 '18 at 11:58

0 Answers0