FluentValidation 1.2 beta 1 is now available to download.

This release contains several new features:

Setting the validator cascade mode

In v1.1, if you have multiple validators defined on a single property then all of those validators will be executed even if the first one fails. This can be changed by calling the Cascade method:

RuleFor(x => x.Surname)
  .Cascade().StopOnFirstFailure()
  .NotNull()
  .Length(1, 250);

In this case, the Length validator would not be run on the Surname property if the NotNull validator fails.

This is customisable globally by setting the static property ValidatorOptions.CascadeMode.

MVC2 Support

The FluentValidationModelBinder has been modified to work with ASP.NET MVC2 RC. Note that if you want to use FluentValidation with MVC1, you will need to use the older 1.1 release.

FluentValidation 1.2 Beta 1 does not currently include the custom ModelMetadataProvider and ModelValidatorProvider that I mentioned in this post.

In its current state, the MVC2 metadata API is not extensible enough to work well with FluentValidtion (see this post for details) so I’ve omitted them from this beta. If MVC2′s support for external frameworks is improved before RTM, then I will consider re-adding these features for the next release.

Custom user state

Custom user state can be stored alongside validation failures:

RuleFor(person => person.Surname).NotNull().WithState(person => "foo")

This state can then be retrieved from the ValidationFailure object if the rule fails:

var result = validator.Validate(model);
var error = result.Errors[0];
var customState= error.CustomState;

OnAnyFailure

Rules can define a callback method that will be invoked if any of the validators associated with a particular rule fail:

RuleFor(person => person.Surname).NotNull().OnAnyFailure(person => {
   Console.WriteLine("#fail");
});

WithPropertyName

The WithPropertyName method can be used to override the name of the property that will be used when associating an error message with a particular property:

public class PersonValidator : AbstractValidator<Person> {
  public PersonValidator() {
    RuleFor(person => person.Surname).NotNull().WithPropertyName("foo");
  }
}
var validator = new PersonValidator();
var result = validator.Validate(new Person());
//property name is 'foo' instead of 'Surname'
string propertyName = result.Errors.Single().PropertyName;

InlineValidator

The InlineValidator can be used to define rules without creating a dedicated validator class:

var validator = new InlineValidator<Person>() {
  v => v.RuleFor(x => x.Surname).NotNull();
  v => v.RuleFor(x => x.Age).GreaterThan(0);
}

ValidateAndThrow

The ValidateAndThrow extension method can be used to throw an exception when validation fails rather than returning a ValidationResult.

Experimental xVal integration

Thanks to Adam Schroder, FluentValidation now includes experimental support for generating xVal rules. I’ve labelled this as “Experimental” as there is currently no support for custom validation messages or some of the more complex FluentValidation rules. The future of the FluentValidation xVal integration also depends on what happens with MVC2′s validation providers and whether xVal will continue to be developed after the MVC2 release.

New PropertyValidator base class (potentially breaking change)

In FluentValidation 1.x, all property validators implemented the IPropertyValidator<T,TProperty> interface. As of v1.2 this has been deprecated in favour of the PropertyValidator base class. Note that property validators themselves are no longer generic, which makes them easier to work with if you need to gather metadata about a validator.

For example, in v1.1 the NotNullValidator looked like this:

[ValidationMessage(Key = "notnull_error")]
public class NotNullValidator<T, TProperty> : IPropertyValidator<T, TProperty> {
	public PropertyValidatorResult Validate(PropertyValidatorContext<T, TProperty> context) {
		if (context.PropertyValue == null) {
			var formatter = new MessageFormatter().AppendProperyName(context.PropertyDescription);
			string error = context.GetFormattedErrorMessage(typeof(NotNullValidator<T, TProperty>), formatter);
 
			return PropertyValidatorResult.Failure(error);
		}
		return PropertyValidatorResult.Success();
	}
}

…while in v1.2 it now looks like this:

public class NotNullValidator : PropertyValidator, INotNullValidator {
	public NotNullValidator() : base(() => Messages.notnull_error) {
		SupportsStandaloneValidation = true;
	}
 
	protected override bool IsValid(PropertyValidatorContext context) {
		if (context.PropertyValue == null) {
			return false;
		}
		return true;
	}
}

The use of a base class helps keep the validator definitions simple. Also note that the ValidationMessage attribute has been removed – localised error messages can now be specified either by passing a resource type and key to the base PropertyValidator constructor or by using a lambda expression.

If you have written any custom property validators, it is recommended that you change them to inherit from PropertyValidator. However, there is a backwards compatibility layer in place which should allow old-style property validators to continue working.

DefaultResourceManager has been removed (breaking change)

In order to add better localization support, the DefaultResourceManager has been removed in favour of Visual Studio’s default generated “Messages” class. If you need to replace this with your own Messages class, you can set the static ResourceProviderType property on the ValidatorOptions class.