RuleSets in FluentValidation

Victor Magalhães
4 min readDec 25, 2023

--

Fluent Validation RuleSets

RuleSet in FluentValidation is a feature that allows you to define and apply groups of validation rules to your objects under specific conditions. It enables you to organize and manage validation rules in a more modular and flexible way. The idea is to group related rules together under a named set, and then selectively apply those rules based on certain criteria.

When defining your validation rules using FluentValidation, you can associate them with a named RuleSet. This is typically done using the RuleSet method.

Define a class to validate

public class Employee
{
// Personal Information
public string Name { get; set; }
public DateTime BirthDate { get; set; }
public string Gender { get; set; }
public string Nationality { get; set; }
public string EducationLevel { get; set; }
public string MaritalStatus { get; set; }

// Contact Information
public string Email { get; set; }
public string Address { get; set; }
public string PhoneNumber { get; set; }

// Legal Information
public string Document { get; set; }
public DateTime DocumentExpirationDate { get; set; }
public string VisaType { get; set; }

// Additional Information
public string SocialSecurityNumber { get; set; } // Health and Legal Information
public string EmergencyContact { get; set; } // Emergency Contact Information
public string BloodType { get; set; } // Health Information
public string Ethnicity { get; set; } // Demographic Information
}

The class already has comments dividing the fields into groups. These groups in a real scenario might even be specific classes, but they will be kept this way for our examples.

  • Personal Information: This group contains essential personal details about the individual, providing insights into their identity, background, and education.
  • Contact Information: This group contains information that enables communication and locates the person, including email, physical address, and phone number.
  • Legal Information: This group contains information related to legal identification, residency status, and related details.
  • Additional Information: This group contains additional information that may be relevant for health, emergency situations, and demographic analysis.

Define validator class

public class EmployeeValidator : AbstractValidator<Employee>
{
public EmployeeValidator()
{
// Always validate "Name" regardless of RuleSet
RuleFor(e => e.Name).NotEmpty().WithMessage("Name cannot be empty.");

// RuleSet "PersonalInformation"
RuleSet("PersonalInformation", () =>
{
RuleFor(e => e.BirthDate).NotEmpty().WithMessage("Birth date must be specified.");
RuleFor(e => e.Gender).NotEmpty().WithMessage("Gender must be specified.");
RuleFor(e => e.Nationality).NotEmpty().WithMessage("Nationality must be specified.");
RuleFor(e => e.EducationLevel).NotEmpty().WithMessage("Education level must be specified.");
RuleFor(e => e.MaritalStatus).NotEmpty().WithMessage("Marital status must be specified.");
});

// RuleSet "ContactInformation"
RuleSet("ContactInformation", () =>
{
RuleFor(e => e.Email).NotEmpty().EmailAddress().WithMessage("Invalid email address.");
RuleFor(e => e.Address).NotEmpty().WithMessage("Address must be specified.");
RuleFor(e => e.PhoneNumber).NotEmpty().WithMessage("Phone number must be specified.");
});

// RuleSet "LegalInformation"
RuleSet("LegalInformation", () =>
{
RuleFor(e => e.Document).NotEmpty().WithMessage("Document must be specified.");
RuleFor(e => e.DocumentExpirationDate).NotEmpty().WithMessage("Document expiration date must be specified.");
RuleFor(e => e.VisaType).NotEmpty().WithMessage("Visa type must be specified.");
});

// RuleSet "AdditionalInformation"
RuleSet("AdditionalInformation", () =>
{
RuleFor(e => e.SocialSecurityNumber).NotEmpty().WithMessage("Social security number must be specified.");
RuleFor(e => e.EmergencyContact).NotEmpty().WithMessage("Emergency contact must be specified.");
RuleFor(e => e.BloodType).NotEmpty().WithMessage("Blood type must be specified.");
RuleFor(e => e.Ethnicity).NotEmpty().WithMessage("Ethnicity must be specified.");
});
}
}

In the provided code, there are four RuleSets defined in the EmployeeValidator. Here are the names of the RuleSets:

  • PersonalInformation: Contains validation rules for personal information such as birth date, gender, nationality, education level, and marital status.
  • ContactInformation: Contains validation rules for contact information such as email, address, and phone number.
  • LegalInformation: Contains validation rules for legal information such as document, document expiration date, and visa type.
  • AdditionalInformation: Contains validation rules for additional information such as social security number, emergency contact, blood type, and ethnicity.

In addition to these specific RuleSets, there is a global rule outside any RuleSet for the Name field. This means that validation for the Name field will be applied independently of the RuleSet used.

Using the validator

var employee = new Employee
{
// Populate employee properties
};

var validator = new EmployeeValidator();

// General validation without a specific RuleSet
validator.Validate(employee);

// RuleSet "PersonalInformation"
validator.Validate(employee, options => options.IncludeRuleSets("PersonalInformation"));

// RuleSet "ContactInformation"
validator.Validate(employee, options => options.IncludeRuleSets("ContactInformation"));

// RuleSet "LegalInformation"
validator.Validate(employee, options => options.IncludeRuleSets("LegalInformation"));

// RuleSet "AdditionalInformation"
validator.Validate(employee, options => options.IncludeRuleSets("AdditionalInformation"));

// Multi RuleSet "PersonalInformation" and "ContactInformation"
validator.Validate(employee, options => options.IncludeRuleSets("PersonalInformation", "ContactInformation"));

// Use all Ruleset
validator.Validate(employee, options => options.IncludeAllRuleSets());

Conclusion

In conclusion, RuleSets in FluentValidation provide a powerful mechanism for organizing and applying validation rules in a modular and flexible manner. By grouping related validation rules under a named set, developers can easily manage and selectively apply rules based on specific conditions or scenarios.

The flexibility of RuleSets allows developers to validate specific sets of rules or combine multiple RuleSets as needed. Furthermore, the ability to define a global rule outside any RuleSet ensures that certain validations are applied universally, regardless of the RuleSet in use.

When using FluentValidation, RuleSets prove invaluable in scenarios where different parts of an object need specialized validation logic. By encapsulating these rules within RuleSets, developers can enhance code readability, maintainability, and adaptability.

In practical applications, RuleSets can be utilized to validate diverse scenarios, such as personal details, contact information, legal requirements, or any other domain-specific rules. Leveraging RuleSets appropriately results in cleaner and more organized validation logic, contributing to a more robust and maintainable codebase.

Ultimately, RuleSets in FluentValidation empower developers to express complex validation requirements in a clear and structured way, enhancing the overall quality and reliability of their applications.

--

--