Using Fluent Validation with ASP.NET MVC - Part 1: The Basics

2 minute read

One of the most popular ways to do model validation in the ASP.NET MVC  Framework is surely to use the built-in model validation features using data annotations.  This will probably work fine in most instances, but I prefer using the Fluent Validation library in my own projects mainly because of how easy it is to unit test validation rules, as well as the fact that I can split the validation rules completely from the underlying model.  Yes, I know you can unit test validation using data annotations as well without too much hassle, but when you need to inject dependencies into your validation rules, things can become a bit tricky.

In any case, as with many things in the software development world there is surely no correct answer as to which method is the best - it comes down to using what you are most comfortable with.  I will be doing a short series on using Fluent Validation with ASP.NET MVC 4, so if you are interested in using it in your own projects then read on.  In this blog post I will show you how to add the FluentValidation class library to your project as well as how to replace the existing data annotations validations with Fluent Validation.

 Integrating Fluent Validation in your project

Fluent Validation is available as a Nuget package, so to install it is as simple as searching for the Fluent Validation package in the Nuget Package Manager.  You can add the package named FluentValidation.MVC as that will install both the core Fluent Validation package as well as the ASP.NET MVC 4 extensions.

Replacing the existing Data Annotations validation

For this basic tutorial we will be taking the existing registration model and change it from using data annotations to using Fluent Validation.  This is what the standard RegistrationModel class looks like which is generated by the default ASP.NET MVC 4 Internet Application template:

public class RegisterModel
{
    [Required]
    [Display(Name = "User name")]
    public string UserName { get; set; }

    [Required]
    [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
    [DataType(DataType.Password)]
    [Display(Name = "Password")]
    public string Password { get; set; }

    [DataType(DataType.Password)]
    [Display(Name = "Confirm password")]
    [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
    public string ConfirmPassword { get; set; }
}

All of the validation rules in this class are placed in a new class called RegisterModelValidator.  For information on the type of validation rules which you can specify please refer to the Fluent Validation documentation on the Built In Validators.

public class RegisterModelValidator : AbstractValidator<RegisterModel>
{
    public RegisterModelValidator()
    {
        RuleFor(x => x.UserName)
            .NotNull();
        RuleFor(x => x.Password)
            .NotNull()
            .Length(6, 100);
        RuleFor(x => x.ConfirmPassword)
            .Equal(x => x.Password);
    }
}

This validation class is then linked to the RegisterModel class by specifying it in the Validator attribute:

[FluentValidation.Attributes.Validator(typeof(RegisterModelValidator))]
public class RegisterModel
{
    [Display(Name = "User name")]
    public string UserName { get; set; }

    [DataType(DataType.Password)]
    [Display(Name = "Password")]
    public string Password { get; set; }

    [DataType(DataType.Password)]
    [Display(Name = "Confirm password")]
    public string ConfirmPassword { get; set; }
}

The final step is to hook up the FluentValidation class library to the ASP.NET MVC 4 validation framework.  To do this you simply need to make a call to the FluentValidationModelValidatorProvider.Configure() method inside your global.asax file.

public class MvcApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();

        WebApiConfig.Register(GlobalConfiguration.Configuration);
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);
        AuthConfig.RegisterAuth();

        FluentValidationModelValidatorProvider.Configure();
    }
}

Next time we will look at adding some unit tests for our new validation classes.

Did you notice an error? Please help me and the other readers by heading over to the GitHub repo for this blog and submit a Pull Request with the corrections.