自定义DataAnnotation IsValid未调用

背景

大家好,

基本上,我在.NET核类库中编写自定义数据注释,它将validationIEnumerable至少具有一定数量的元素。


问题

出于某种原因,在运行validation时,永远不会调用IsValid。 我已经找到了一些关于这个问题的其他SO问题,但它们都有一个与我不同的问题(基本上,它们实际上并没有validation它们的对象)。 但是,我正在validation我的对象(调用Validator.TryValidateObject(...) )但是,从未调用过IsValid。

如果我使用任何开箱即用的validation属性(例如必需),它将按预期运行。


代码

MinElementsAttribute.cs

 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; if(list == null || list.Count() < this.minElements) { return new ValidationResult(this.FormatErrorMessage(validationContext.DisplayName)); } return ValidationResult.Success; } } 

MinElementsTests.cs

 [Fact] public void TestValidation() { var validationResults = new List(); 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 Assert.False(isValid); Assert.NotEmpty(validationResults); } internal class TestObject { public TestObject() { this.StringList = new List(); } [MinElements(3)] public List StringList { get; set; } } 

编辑:解决方案

请参阅解决方案的已接受答案。 我想添加这一点还要注意,通过将inheritance更改为RequiredAttribute而不是ValidationAttribute,可以隐式强制执行所有对象属性的validation。

Validator.TryValidateObject类有一些重载方法。 你想用这个:

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

来自MSDN文章 :

validateAllProperties
类型:System.Boolean
如果validation所有属性,则为true 如果为false,则仅validation所需的属性。

您必须使用此方法,因为您的属性不是从RequiredAttribute类派生的。

我的样品

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