I really like Jeremy Skinner’s FluentValidation library and have used it on a couple of projects. Up until now though, I’ve only be using it to validate single properties in isolation.
The other day a colleague and I were trying to create a rule that validated two properties by querying the database and checking that the combination didn’t already exist. But we couldn’t seem to work it out.
I cheekily pinged @JeremySkinner and he helpfully pointed out that there are several ways of validating multiple properties:
- if you want to do cross property comparison then RuleFor(x => x.Foo).GreaterThan(x => x.Bar) etc
- you can also use Must: RuleFor(x => x.Foo).Must((instance, foo) => …)
- usually those cover most scenarios. If not, then there’s also Custom, but that’s usually a last resort
The second option was what worked for us, and here is an example.
public class FooBarRequestValidator : AbstractValidator<FooBarRequest>
{
private readonly IRepository repository;
public FooBarRequestValidator(IRepository repository)
{
this.repository = repository;
RuleFor(x => x.Foo)
.Must(NotAlreadyHaveABar)
.WithMessage("You already have a bar for this foo.");
}
private bool NotAlreadyHaveABar(FooBarRequest instance, string foo)
{
return !repository.GetAll<FooBar>()
.Any(x => x.Foo == foo && x.Bar == instance.Bar);
}
}
The trick is using the overload of Must() that takes a Func<T, TProperty, bool> predicate: that gives you access to the whole instance for your validating pleasure. Here, in NotAlreadyHaveABar() I can access Bar even though the rule is for the Foo property.
This works with FluentValidation v1.1 up to v2.0 Beta 1.

