Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

FluentValidation and Unity

0.00/5 (No votes)
12 Feb 2012 3  
Using Fluent Validation with Unity in a Silverlight application

Introduction

Validation is often the bane of a development project. It's critical to usability and data integrity (and often security, when ensuring data is not an attempt to attack the application), but it can be very time consuming to write the validation code and handle all of the permutations. Luckily Jeremy Skinner has created an excellent open source validation framework called Fluent Validation for .NET. Jeremy has created a lot of documentation, so this article will not cover the features and usage of Fluent Validation for .NET. One feature the documentation does not cover is how to pass the validation object via dependency injection when using Unity, which is an Inversion of Control (IoC) container. This article addresses how to do this. For the attached example I've used Silverlight, but the same techniques can be used with WPF.

Background

Dependency injection is a useful pattern to acheive loose coupling and also simplify testing by allowing dependencies to be stubbed or mocked. By being able to pass a validation object into a business object or view model (in the case of MVVM), tests can be written for the business object or view model without requiring the business object or view model to be valid. The validation object can be stubbed to always pass or fail as required.

This article does not cover unit tests, mocking, and dependency injection. It is assumed that the reader is already conversant with these techniques.

Using the code

The first step is to create a Unity validator factory from the ValidatorFactoryBase provided by Fluent Validation for .NET. The important code is the override for CreateInstance, which allows the factory to return the correct validation object from the Unity container.

public class UnityValidatorFactory : ValidatorFactoryBase
{
    private readonly IUnityContainer _container;

    public UnityValidatorFactory(IUnityContainer container)
    {
        _container = container;
    }

    public override IValidator CreateInstance(Type validatorType)
    {
        return _container.Resolve(validatorType) as IValidator;
    }
}

The next step is to register the factory with the Unity container. In the attached example, this is done in the Bootstrapper.cs class.

Container.RegisterType<IValidatorFactory, UnityValidatorFactory>(new ContainerControlledLifetimeManager());

Now the validation class can be created by inheriting from the AbstractValidator base class. See Fluent Validation for .NET documentation for more information about how to build validation rules from this base class.

public class MainPageViewModelValidator : AbstractValidator<IMainPageViewModel>
{
    public MainPageViewModelValidator()
    {
        RuleFor(x => x.FirstName)
            .NotEmpty()
            .WithMessage("First name cannot be blank.");

        RuleFor(x => x.LastName)
            .NotEmpty()
            .WithMessage("Last name cannot be blank.");

        RuleFor(x => x.Age)
            .NotEmpty()
            .WithMessage("Age is required.");

        RuleFor(x => x.Age)
            .Must(a => a.IsInt32())
            .When(x => !x.Age.IsNullOrEmpty())
            .WithMessage("Age must be an integer.");
    }
}

The validation class must also be registered with Unity. In the attached example, this is also registered in Bootstrapper.cs. The IValidator generic interface is assigned the interface for the view model and the registered implementation is the view model validator.

Container.RegisterType<IValidator<IMainPageViewModel>, MainPageViewModelValidator>(new ContainerControlledLifetimeManager());

Now a ViewModel can access the validation object by passing the validation factory in as a dependency and requesting the required validation object.

using FluentValidation;

private readonly IValidator<IMainPageViewModel> _validator;

public MainPageViewModel(IValidatorFactory validatorFactory)
{
    _validator = validatorFactory.GetValidator<IMainPageViewModel>();
}

The validation object can then be used as required, either validating the whole view model, or just a property (which can be useful when implementing IDataErrorInfo, as shown in the attached example). An example of validating a property is shown below. Note that a validation object can return more than one error, so the ValidationResult contains an Errors collection.

public string FirstName
{
    get { return _firstName; }
    set
    {
        if (_firstName != value)
        {
            _firstName = value;
            RaisePropertyChanged("FirstName");
        }

        // validate - even if no change
        ClearError("FirstName");
        var validationResult = _validator.Validate(this, "FirstName");
        if (!validationResult.IsValid)
        {
            validationResult.Errors.ToList().ForEach(x => SetError("FirstName", x.ErrorMessage));
        }
    }
}

History

  • July 2011 - initial release.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here