Skip to content

Add support for validating complex or collection properties using System.ComponentModel.DataAnnotations.Validator #31400

Closed
@pranavkm

Description

@pranavkm

Background

Validator.TryValidateObject does not support validating complex sub-properties or collection types. From the docs:

It validates the property values of the object if validateAllProperties is true but does not recursively validate properties of the objects returned by the properties.

Validation attributes or IValidatableObject contracts applied to sub-properties or entries in collection properties are ignored by this API. Users have been working around this by developing their own solutions such as the one described here - http://www.technofattie.com/2011/10/05/recursive-validation-using-dataannotations.html. MVC supports DataAnnotations attributes applied to models, but does it's own graph walking so doesn't have to deal with this issue.

Blazor on the other hand relies on the Validator.TryValidateObject API for it's validation. We've had reports where users are confused \ surprised by this behavior. For the 3.1 \ 3.2 releases, we're shipping an experimental package - https://www.nuget.org/packages/Microsoft.AspNetCore.Components.DataAnnotations.Validation/ with APIs that support validating complex \ collection type properties. For the 5.0 release, we'd like for the runtime to support this feature.

API proposal

Basing this proposal based on the experimental package that's shipping as part of Blazor

Introduce a new attribute ValidateComplexTypeAttribute that allows Validator to recurse in to complex or collection type properties. It's important to note that this only recurses one level. This avoids coming up strategies to limit traversing in to arbitrary object graphs.

We introduce overloads to Validator.TryValidateObject and Validator.ValidateObject that allows navigating in to properties that are ValidateComplexTypeAttribute. The documentation for the existing overloads explicitly state that they does not recurse in to properties. Changing it's behavior isn't desirable given how stable this API has been.

Usage

class Person
{
     ....
    [ValidateComplexType]
    public Address Address { get; set; } = new Address();
}

Person person = GetPerson();
Validator.TryValidateObject(person);

API diff

namespace System.ComponentModel.DataAnnotations
{
   public class ValidateComplexTypeAttribute : ValidationAttribute {}

    public static class Validator
    {
      public static bool TryValidateObject(object instance, System.ComponentModel.DataAnnotations.ValidationContext validationContext, System.Collections.Generic.ICollection<System.ComponentModel.DataAnnotations.ValidationResult> validationResults, bool validateAllProperties, bool validateComplexTypeProperties) { throw null; }

      public static void ValidateObject(object instance, System.ComponentModel.DataAnnotations.ValidationContext validationContext, bool validateAllProperties, bool validateComplexTypeProperties) { }
    }
}

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions