Using FluentValidation with an IoC Container

In my recent FluentValidation presentation I mentioned that if you’re going to be using FluentValidation with ASP.NET MVC then you should probably be using an Inversion of Control container rather than using the AttributedValidatorFactory.

What is a Validator Factory?

A validator factory is a class responsible for creating validator instances. The IValidatorFactory interface looks like this:

public interface IValidatorFactory {
  IValidator<T> GetValidator<T>();
  IValidator GetValidator(Type type);
}

The interface has two methods – one generic, one not. The GetValidator method will receive a Type instance representing the type of object that needs to be validated and it is the responsibility of this factory to create and return the appropriate validator instance.

Creating your own Validator Factory

To create your own Validator Factory you can either implement IValidatorFactory directly, or inherit from the ValidatorFactoryBase class (which does some of the work for you). In this example I’m going to create a validator factory that leverages StructureMap.

Firstly, you’ll need to register your validator types with StructureMap:

ObjectFactory.Configure(cfg => cfg.AddRegistry(new MyRegistry()));
 
public class MyRegistry : Registry {
  public MyRegistry() {
    For<IValidator<Person>>()
	.Singleton()
	.Use<PersonValidator>();
  }
}

Here I am configuring StructureMap using a custom Registry. In the Registry I tell StructureMap that when it is asked to instantiate an IValidator<Person>, it should return a PersonValidator.

Now, you can write a custom ValidatorFactory that leverages StructureMap to instantiate the validator:

public class StructureMapValidatorFactory : ValidatorFactoryBase {
	public override IValidator CreateInstance(Type validatorType) {
		return ObjectFactory.TryGetInstance(validatorType) as IValidator;
	}
}

In the CreateInstance method you receive a Type object that represents the type of validator that the framework requires (for example, typeof(IValidator<Customer>)). This method should attempt to instantiate the appropriate type (CustomerValidator) and return it (or return null if no such type exists).

Using the AssemblyScanner

The next version of FluentValidation (1.2) will also include an “AssemblyScanner” class that makes it very easy to automatically register all of the validator classes in a particular assembly with your IoC container. Using the AssemblyScanner, the MyRegistry class could look like this:

public class MyRegistry : Registry {
  public MyRegistry() {
 
    AssemblyScanner.FindValidatorsInAssemblyContaining<MyValidator>()
      .ForEach(result => {
           For(result.InterfaceType)
              .Singleton()
              .Use(result.ValidatorType);
      });
 
  }
}

Note that this functionality is not in the current 1.2 beta 3 release, but will be in 1.2 RC (or you can grab it from the source code).

Using the Factory with MVC

If you want to make use of FluentValidation’s ASP.NET MVC integration then you need to pass your ValidatorFactory to the FluentValidationModelValidatorProvider in your application startup routine:

protected void Application_Start() {
	RegisterRoutes(RouteTable.Routes);
 
	//Configure structuremap
	ObjectFactory.Configure(cfg => cfg.AddRegistry(new MyRegistry()));
	ControllerBuilder.Current.SetControllerFactory(new StructureMapControllerFactory());
 
	//Configure FV to use StructureMap
	var factory = new StructureMapValidatorFactory();
 
	//Tell MVC to use FV for validation
	ModelValidatorProviders.Providers.Add(new FluentValidationModelValidatorProvider(factory));        
	DataAnnotationsModelValidatorProvider.AddImplicitRequiredAttributeForValueTypes = false;
}

…and that’s it. FluentValidation will now use StructureMap to instantiate validator instances as it requires them.

Sample code from this post can be downloaded from here.

Written on February 22, 2010