FluentValidation version 1.1 is now available to download.

Quick recap: What is FluentValidation?

FluentValidation allows you to use a fluent interface and lambda expressions to define validation rules for your objects:

public class CustomerValidator: AbstractValidator<Customer> {
  public CustomerValidator() {
    RuleFor(customer => customer.Surname).NotEmpty();
    RuleFor(customer => customer.Forename).NotEmpty().WithMessage("Please specify a first name");
    RuleFor(customer => customer.Discount).NotEqual(0).When(customer => customer.HasDiscount);
    RuleFor(customer => customer.Address).Length(20, 250);
    RuleFor(customer => customer.Postcode).Must(BeAValidPostcode).WithMessage("Please specify a valid postcode");
  }
 
  private bool BeAValidPostcode(string postcode) {
    // custom postcode validating logic goes here
  }
}

…which can then be executed against a particular instance of your class:

Customer customer = new Customer();
CustomerValidator validator = new CustomerValidator();
ValidationResult results = validator.Validate(customer);
 
bool validationSucceeded = results.IsValid;
IList<ValidationFailure> failures = results.Errors;

What’s new in version 1.1?

Quite a lot of FluentValidation has been re-written with the 1.1 release, but these are the changes most noticable to the end user:

Nested Validators

It is now possible to re-use validators. For example, if you have a Customer object that has a property of type Address, then you can declare an AddressValidator like this:

public class AddressValidator : AbstractValidator<Address> {
   public AddressValidator() {
        RuleFor(x => x.Property).NotNull().Length(1, 250);
        RuleFor(x => x.District).NotNull().Length(1, 250);
        RuleFor(x => x.Country)...
        //etc
   }
}

…and then your CustomerValidator can specify that the Address property should be validated using the AddressValidator:

public class CustomerValidator : AbstractValidator<Customer> {
    public CustomerValidator() {
       RuleFor(x => x.Surname).NotNull();
       RuleFor(x => x.Address).SetValidator(new AddressValidator()); 
    }
}

Additional Language Translations

Thanks to several user contributions, the default validation messages are now available in German, Spanish, French, Dutch and Portuguese in addition to English.

Chaining Validators

In version 1.0, if you wanted to specify multiple validation rules on a single property then you had to use the ‘And’ operator:

RuleFor(x => x.Name).NotNull().And.NotEqual("foo");

…but in v1.1 these can now be chained together directly:

RuleFor(x => x.Name).NotNull().NotEqual("foo");

IValidatorSelector

The new IValidatorSelector interface allows you to specify which validation rules should be executed when performing validation. I’m planning a more in-depth post on this in the future.

Message Formatting Placeholders

Custom validation messages can now use special placeholders, eg:

RuleFor(x => x.Surname).NotNull().WithMessage("You must enter a value for {PropertyName}!");

There’s a complete list of placeholders in the documentation. I plan to write a more detailed post about how to use custom placeholders in your own, custom validators in the future.

What’s coming in v1.2?

For version 1.2, I’m planning on incorporating Adam’s work on adding xVal integration for FluentValidation as well as adding a sample application.