NotEmpty for collection is not working

Aug 24, 2009 at 5:06 PM

 

Person.Orders = new List<order>();

RuleFor(customer=>customer.Orders).NotEmpty();

does not return false value. Rule succeeds. I would like to NotEmpty should validate Length for the colleciton object.

Right now i added my own validatior for colleciton.

public class NotEmptyListValidator<TInstance, TProperty> : IPropertyValidator<TInstance, IList<TProperty>>

{

public PropertyValidatorResult Validate(PropertyValidatorContext<TInstance, IList<TProperty>> context)

{

if (Equals(context.PropertyValue, default(TProperty))||context.PropertyValue.Count ==0)

{

var formatter = new MessageFormatter().AppendProperyName(context.PropertyDescription);

string error = context.GetFormattedErrorMessage(typeof(NotEmptyValidator<TInstance, TProperty>), formatter);

return PropertyValidatorResult.Failure(error);

}

return PropertyValidatorResult.Success();

}

}

 

But still i does not allow me use ICollection as a paramater.

Do i need to add one for each collection type . Is there better way to implement the code.

Thanks

Sendil

Coordinator
Aug 24, 2009 at 5:32 PM

NotEmpty isn't really designed to work with collections - it simply checks whether the property's value is equal to the default value for that type. I would suggest simply validating the .Count propert of the collection:

RuleFor(x => x.Orders.Count).GreaterThan(0)

If you want to use your NotEmptyListValidator with ICollection<T> then you'll need to implement it using generic type constraints as C# 3 does not support generic covariance:

 

public class NotEmptyListValidator<TInstance, TProperty, TCollectionElement> : IPropertyValidator<TInstance, TProperty> where TProperty : ICollection<TCollectionElement> {
	public PropertyValidatorResult Validate(PropertyValidatorContext<TInstance, TProperty> context) {
		if (Equals(context.PropertyValue, default(TProperty)) || context.PropertyValue.Count == 0) {

			var formatter = new MessageFormatter().AppendProperyName(context.PropertyDescription);

			string error = context.GetFormattedErrorMessage(typeof(NotEmptyValidator<TInstance, TProperty>), formatter);

			return PropertyValidatorResult.Failure(error);

		}

		return PropertyValidatorResult.Success();

	}
}

public static class ValidatorExtensions {
	public static IRuleBuilderOptions<T, TProperty> NotEmptyCollection<T, TProperty, TCollectionElement>(this IRuleBuilder<T, TProperty> ruleBuilder) where TProperty: ICollection<TCollectionElement> {
		return ruleBuilder.SetValidator(new NotEmptyListValidator<T, TProperty, TCollectionElement>());
	}
}

However, the downside of this approach is that the type inference will not work so you have to explicitly specify the generic types:

validator.RuleFor(x => x.Orders).NotEmptyCollection<Person, IList<Order>, Order>();

 

May 27, 2013 at 3:20 AM
Very useful. It would be nice if there was a way to infer types. But I believe it is a limitation of language.