Article Categories
- All Categories
-
Data Structure
-
Networking
-
RDBMS
-
Operating System
-
Java
-
MS Excel
-
iOS
-
HTML
-
CSS
-
Android
-
Python
-
C Programming
-
C++
-
C#
-
MongoDB
-
MySQL
-
Javascript
-
PHP
-
Economics & Finance
What is use of fluent Validation in C# and how to use in C#?
FluentValidation is a powerful .NET library for building strongly-typed validation rules using a fluent interface and lambda expressions. It helps separate validation logic from your domain models, making your code cleaner and more maintainable by centralizing validation rules in dedicated validator classes.
The library provides an intuitive way to define complex validation rules with built-in validators, custom validation methods, and detailed error messaging. It's particularly useful in web applications, APIs, and any scenario where robust input validation is required.
Installation
To use FluentValidation in your project, install the NuGet package −
<PackageReference Include="FluentValidation" Version="11.8.0" />
Syntax
FluentValidation validators inherit from AbstractValidator<T> and define rules using the RuleFor method −
public class ModelValidator : AbstractValidator<Model> {
public ModelValidator() {
RuleFor(x => x.Property)
.NotEmpty()
.Length(min, max)
.WithMessage("Custom error message");
}
}
Basic FluentValidation Example
Here's a complete example demonstrating validation of a person model with multiple validation rules −
using System;
using System.Collections.Generic;
using System.Linq;
using FluentValidation;
using FluentValidation.Results;
public class PersonModel {
public string FirstName { get; set; }
public string LastName { get; set; }
public decimal AccountBalance { get; set; }
public DateTime DateOfBirth { get; set; }
}
public class PersonValidator : AbstractValidator<PersonModel> {
public PersonValidator() {
RuleFor(p => p.FirstName)
.Cascade(CascadeMode.StopOnFirstFailure)
.NotEmpty().WithMessage("{PropertyName} is Empty")
.Length(2, 50).WithMessage("Length ({TotalLength}) of {PropertyName} Invalid")
.Must(BeAValidName).WithMessage("{PropertyName} Contains Invalid Characters");
RuleFor(p => p.LastName)
.Cascade(CascadeMode.StopOnFirstFailure)
.NotEmpty().WithMessage("{PropertyName} is Empty")
.Length(2, 50).WithMessage("Length ({TotalLength}) of {PropertyName} Invalid")
.Must(BeAValidName).WithMessage("{PropertyName} Contains Invalid Characters");
RuleFor(p => p.AccountBalance)
.GreaterThanOrEqualTo(0).WithMessage("Account balance cannot be negative");
RuleFor(p => p.DateOfBirth)
.LessThan(DateTime.Today).WithMessage("Date of birth must be in the past");
}
protected bool BeAValidName(string name) {
if (string.IsNullOrWhiteSpace(name)) return false;
name = name.Replace(" ", "").Replace("-", "");
return name.All(char.IsLetter);
}
}
static class Program {
static void Main(string[] args) {
List<string> errors = new List<string>();
PersonModel person = new PersonModel {
FirstName = "",
LastName = "S",
AccountBalance = 100,
DateOfBirth = DateTime.Now.Date
};
PersonValidator validator = new PersonValidator();
ValidationResult results = validator.Validate(person);
if (!results.IsValid) {
foreach (ValidationFailure failure in results.Errors) {
errors.Add(failure.ErrorMessage);
}
}
foreach (var item in errors) {
Console.WriteLine(item);
}
}
}
The output of the above code is −
FirstName is Empty Length (1) of LastName Invalid Date of birth must be in the past
Advanced Validation with Conditional Rules
FluentValidation supports conditional validation using When and complex business rules −
using System;
using FluentValidation;
using FluentValidation.Results;
public class UserModel {
public string Email { get; set; }
public int Age { get; set; }
public string PhoneNumber { get; set; }
public bool IsVip { get; set; }
}
public class UserValidator : AbstractValidator<UserModel> {
public UserValidator() {
RuleFor(u => u.Email)
.NotEmpty().WithMessage("Email is required")
.EmailAddress().WithMessage("Invalid email format");
RuleFor(u => u.Age)
.GreaterThan(0).WithMessage("Age must be greater than 0")
.LessThan(120).WithMessage("Age must be realistic");
RuleFor(u => u.PhoneNumber)
.NotEmpty().WithMessage("Phone number is required")
.When(u => u.IsVip, ApplyConditionTo.CurrentValidator)
.WithMessage("VIP users must provide a phone number");
RuleFor(u => u.Age)
.GreaterThanOrEqualTo(21).WithMessage("VIP users must be at least 21 years old")
.When(u => u.IsVip);
}
}
static class Program {
static void Main(string[] args) {
UserModel user = new UserModel {
Email = "invalid-email",
Age = 18,
PhoneNumber = "",
IsVip = true
};
UserValidator validator = new UserValidator();
ValidationResult result = validator.Validate(user);
if (!result.IsValid) {
foreach (var error in result.Errors) {
Console.WriteLine($"{error.PropertyName}: {error.ErrorMessage}");
}
} else {
Console.WriteLine("Validation passed!");
}
}
}
The output of the above code is −
Email: Invalid email format PhoneNumber: Phone number is required Age: VIP users must be at least 21 years old
Key Benefits of FluentValidation
| Feature | Benefit |
|---|---|
| Separation of Concerns | Validation logic is separated from domain models |
| Fluent Interface | Readable and maintainable validation rules |
| Custom Validators | Easy to create complex business validation rules |
| Conditional Validation | Rules can be applied based on conditions |
| Localization Support | Error messages can be easily localized |
Conclusion
FluentValidation provides a clean, maintainable approach to input validation in .NET applications. It separates validation concerns from your domain models and offers powerful features like conditional rules, custom validators, and detailed error messaging, making it an excellent choice for robust validation scenarios.
