johnny 5
johnny 5

Reputation: 20995

Fluent Validation Filter Arguments For collectionValidator

I'm trying to filter arguments to use in a collection validator using FluentValidations:

I have a generic Class for Collections which looks like:

public class ItemCollection<TEntity>
{
    public ItemCollection(TEntity[] items);
    public TEntity[] Items { get; }
}

I have a Validator for my ItemCollection which looks like so:

public FooCollectionValidator:  AbstractValidator<ItemCollection<Foo>>
{

    public FooCollectionValidator(IDictionary<string, FooMetadata> allowedMetadata)
    {
        //Setting Rules using Must works fine
        this.RuleForEach(x => x.Items).Must(x => allowedMetadata.ContainsKey(x.Key));
    }
}

I Need to set a Validator For each on of the Item but I would like to filter my Metadata For the Child Validator No matter what way I try I don't have access to the items to be able to filter:

this.RuleForEach(x => x.Items).SetValidator(x =>
{            
    //I want to filter the metadata by the Key and pass it to the child validator
    var metadata = allowedMetadata[x.Key];
    return new FooDTOValidator(metadata )       
});

This Doesn't work because X always refers to the collection and not the individual item. How can I filter arguments passed to a collection validator?

Upvotes: 0

Views: 1251

Answers (1)

ChristianMurschall
ChristianMurschall

Reputation: 1671

I fumbled a bit around and it does not seem possible with SetValidator. SetCollectionValidator as suggested is or will be deprecated. The only way I can think of is this:

this.RuleForEach(x => x.Items).Must(x =>
  {
      var validator = new FooDTOValidator(allowedMetadata[x.Key]);
      return validator.Validate(x).IsValid;
  });

Edit As noted in the comment we loose our error messages. There might be a chance to preserve them. Take this as not tested but according to the docs we can get the Root Context Data and add our failures if any.

this.RuleForEach(x => x.Items).Custom((x, context) =>
{
    var validator = new FooDTOValidator(allowedMetadata[x.Key]);
    var result = validator.Validate(x);
    if (!result.IsValid)
    {
        foreach (var failure in result.Errors)
        {
            context.AddFailure(failure);
        }
    }
});

Upvotes: 2

Related Questions