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
.