Stephen Porter Stephen Porter - 11 months ago 67
C# Question

Custom DataAnnotation IsValid Not Called


Hello all,

Basically, I am writing a custom data annotation in a .NET Core Class Library that will validate that an IEnumerable has at least a certain number of elements.

The Problem

For some reason, when running the validation, the IsValid is never called. I have already found a few other SO questions regarding this issue, but they all have a different problem than I do (basically, they weren't actually validating their objects). I am, however, validating my object (calling
) and yet, the IsValid is never called.

If I use any of the out-of-the-box validation attribute (e.g. Required), it operates as expected.

The Code


public class MinElementsAttribute : ValidationAttribute
readonly int minElements;

public MinElementsAttribute(int minElements) : base($"Collection must have a size of at least {minElements}")
this.minElements = minElements;

protected override ValidationResult IsValid(object value, ValidationContext validationContext)
var list = value as IEnumerable<object>;

if(list == null || list.Count() < this.minElements)
return new ValidationResult(this.FormatErrorMessage(validationContext.DisplayName));

return ValidationResult.Success;


public void TestValidation()
var validationResults = new List<ValidationResult>();
var testObject = new TestObject();

// Should be false since I have not added anything to the list
var isValid = Validator.TryValidateObject(testObject, new ValidationContext(testObject), validationResults);

// Fails since isValid comes back as true because IsValid on MinElementsAttribute is never called

internal class TestObject
public TestObject()
this.StringList = new List<string>();

public List<string> StringList { get; set; }

Edit: The Solution

Please see the accepted answer for the solution. I wanted to add this to also note that by changing the inheritance to be from RequiredAttribute rather than ValidationAttribute, you can enforce the validation of all object properties implicitly.

Answer Source

Validator.TryValidateObject class has a few overload methods. You want to use this one:

public static bool TryValidateObject(object instance, ValidationContext validationContext, ICollection<ValidationResult> validationResults, bool validateAllProperties);

From the MSDN article:

Type: System.Boolean
true to validate all properties; if false, only required attributes are validated.

You must use this method, because your attribute does not derive from the RequiredAttribute class.

My Sample

var validationResults = new List<ValidationResult>();            
var testObject = new TestObject();
ValidationContext contexts = new ValidationContext(testObject, null, null);            
var isValid = Validator.TryValidateObject(testObject, contexts, validationResults, true);