Add Validation rules with FluentValidation

One scenario we have in almost all applications where requires user inputs, are validation rules. We have lot of different ways to implement validation (both server and client sides), and one of these ways is using a library called FluentValidation, where it uses lambda expressions to build all validation rules.

To integrate it, we can get the package from Nuget and add it to our project:

fluentvalidation nuget

This will add FluentValidation references.

For this example, we’ll use a simple model such as:

public class Person
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Address { get; set; }
    public int Age { get; set; }
}

Now, to create our validator, we need to have a class who inherits from AbstractValidator, where T in this case will the Person.

using FluentValidation;
using FluentValidationExample.Models;
namespace FluentValidationExample.Validators
{
    public class PersonValidator : AbstractValidator<Person>
    {
    }
}

Having our class created, we can now define the rules to validate a Person entity in the validator class constructor. For this example, I’ll add two rules, one to validate if the first name is not empty and other to make sure we have a age greater than 18.

public PersonValidator()
{
    RuleFor(d => d.FirstName)
        .NotEmpty()
        .WithMessage("First name cannot be empty");

    RuleFor(d => d.Age)
        .Must(AgeMustBeGreaterThan18)
        .WithMessage("Age must be greater than 18");
}

private bool AgeMustBeGreaterThan18(int age)
{
    return age > 18;
}

FluentValidation already includes some built-in validations, so for our first validation we can use the NotEmpty() method. For the second validation, we’ve created a new method who verifies the Age property value and makes sure is greater than 18. If not, it will throw an error.

In this case, the validator will go through all rules and will send the result back with any errors, but we can decide to stop on the first failure.

public PersonValidator()
{
    RuleFor(d => d.FirstName)
        .Cascade(CascadeMode.StopOnFirstFailure)
        .NotEmpty()
        .WithMessage("First name cannot be empty");

    RuleFor(d => d.Age)
        .Must(AgeMustBeGreaterThan18)
        .WithMessage("Age must be greater than 18");
}

private bool AgeMustBeGreaterThan18(int age)
{
    return age > 18;
}

Having the validator created, we now need to call it when we want to validate all rules for the Person model, check if there are any errors, and display (and log) those to the user.

static void Main(string[] args)
{
    var person = new Person
    {
        FirstName = "",
        LastName = "Salgado",
        Age = 17, // I wish
        Address = "London, UK"
    };

    var validator = new PersonValidator();

    var validationResult = validator.Validate(person);

    if (!validationResult.IsValid)
    {
        validationResult.Errors.ToList().ForEach(p => Console.WriteLine(p.ErrorMessage));
    }

    Console.Read();
}

I’m not defining the FirstName and i’ve set the age as 17 to force both rules to fail, so the output will be both error messages:

console output

This is just a example of how we can add FluentValidation to a project, but much more advanced validations can be done, so I recommend you to read the documentation and follow the examples available in the project page.