DEV Community

Cover image for FluentValidation Rule Sets
Karen Payne
Karen Payne

Posted on

FluentValidation Rule Sets

Introduction

Learn how to use rule sets which allow developers to group validation rules together which can be executed together as a group whilst ignoring other rules or execute all rules.

The conventional use of Fluent Validation is to create a model followed by creating a validator class. In the example below, each property has there own validator class which allows reuse.

public class PersonValidator : AbstractValidator<IPerson>
{
    public PersonValidator()
    {
        Include(new IdentifierValidator());
        Include(new FirstNameValidator());
        Include(new LastNameValidator());
        Include(new BirthDateValidator());
        Include(new AddressValidator());
        Include(new EmailValidator());
    }
}
Enter fullscreen mode Exit fullscreen mode

Sample property validator for FirstName property.

public class FirstNameValidator : AbstractValidator<IPerson>
{
    public FirstNameValidator()
    {
        RuleFor(person => person.FirstName)
            .NotEmpty()
            .MinimumLength(3);
    }
}
Enter fullscreen mode Exit fullscreen mode

Using conventional validation works great the majority of work for validation. There are times when not all properties require validations like when adding a new record for EF Core which assigns an identifier.

Rule sets

Rules sets are setup as shown below where FirstName and LastName are a group while other properties are setup separately. This means that rules can be included or excluded for validating an object.

public class PersonValidator : AbstractValidator<Person>
{

    public PersonValidator()
    {
        RuleSet("Names", () =>
        {
            RuleFor(x => x.FirstName).NotNull();
            RuleFor(x => x.LastName).NotNull();
        });

        RuleSet("Identifier", () =>
        {
            RuleFor(x => x.PersonId).NotEqual(0);
        });

        RuleSet("Birth", () =>
        {
            RuleFor(x => x.BirthDate).BirthDateRule();
        });

        RuleSet("Email", () =>
        {
            RuleFor(x => x.EmailAddress).NotEmpty().EmailAddress();
        });
    }
}
Enter fullscreen mode Exit fullscreen mode

Example to exclude the Identifier rule.

var validator = new PersonValidator();

ValidationResult result = validator.Validate(MockedData.InvalidPerson, options => options.IncludeRuleSets(
    "Names",
    "Birth"));


if (result.IsValid)
{
    Console.WriteLine("Validation succeeded.");
}
else
{
    foreach (var error in result.Errors)
    {
        AnsiConsole.MarkupLine($"{error.PropertyName,-14} [red]Error:[/] {error.ErrorMessage}");
    }
}
Enter fullscreen mode Exit fullscreen mode

Example to include all rules

Using the wildcard indicates to include all rules.

Using wildcard

var validator = new PersonValidator();

// Use wildcard to include all rule sets

var result = validator.Validate(
    MockedData.InvalidPerson, options => options.IncludeRuleSets("*"));

if (result.IsValid)
{
    Console.WriteLine("Validation succeeded.");
}
else
{
    foreach (var error in result.Errors)
    {
        AnsiConsole.MarkupLine($"{error.PropertyName,-14} [red]Error:[/] {error.ErrorMessage}");
    }
}   
Enter fullscreen mode Exit fullscreen mode

Source code

Provides code samples using mocked data to try out rule sets.

Console project

Summary

Rule sets open up possibilities not only for validation in applications but also for test projects.

See also

FluentValidation tips C#

Top comments (0)