Ever feel like you’re fighting Blazor’s default validation just to keep your forms clean and your logic sane? You’re not alone. Most Blazor devs stumble into the world of DataAnnotations
and soon realize the limitations: they’re verbose, not very expressive, and get messy as your models grow. That’s where FluentValidation enters the scene like a breath of fresh C# air.
Why Choose FluentValidation for Blazor?
FluentValidation is more than just another library — it’s a developer-friendly toolkit that brings expressive, reusable, and clean validation rules to your form models. With FluentValidation, you can:
- Define rules in a clean and readable syntax
- Keep validation logic out of your data models
- Reuse rules across multiple components
- Support complex conditional logic and localization
In a nutshell, FluentValidation plays nicely with Blazor while freeing you from the clunky confines of DataAnnotations
.
The Problem with Default Validation in Blazor
Blazor’s built-in validation relies heavily on DataAnnotations
, which work fine for simple cases but fall apart when things get complex. Here are some pain points:
- Tight coupling between model and validation logic
- Verbose attribute-based rules
- No support for advanced scenarios like conditionals, rule sets, or custom messages
- Difficult to reuse validation logic across models or components
If you’ve ever tried validating nested objects or needed different rule sets per UI state, you’ve probably already outgrown DataAnnotations
.
Introducing FluentValidation
FluentValidation is a .NET library that lets you write validation rules with a fluent API. It’s expressive, testable, and supports advanced scenarios out-of-the-box.
Here’s a taste:
public class PersonValidator : AbstractValidator<Person>
{
public PersonValidator()
{
RuleFor(x => x.Name).NotEmpty().WithMessage("Name is required");
RuleFor(x => x.Age).InclusiveBetween(18, 60);
}
}
Readable? Definitely. Reusable? Absolutely. Cross-platform? Yep — works with .NET Core, ASP.NET, Blazor, and more.
Setting Up FluentValidation in a Blazor Project
Installing the Required Packages
First, grab the necessary NuGet packages:
Install-Package FluentValidation
Install-Package FluentValidation.DependencyInjectionExtensions
Install-Package BlazorFluentValidation
Configuring FluentValidation in Dependency Injection
In your Program.cs
, register the validators:
builder.Services.AddValidatorsFromAssemblyContaining<PersonValidator>();
builder.Services.AddFluentValidation();
This ensures Blazor knows how to wire up the validators when rendering forms.
Creating and Using Validators
Writing a Basic Validator Class
Let’s say you have a RegisterModel
:
public class RegisterModel
{
public string Email { get; set; }
public string Password { get; set; }
}
Here’s the FluentValidation validator:
public class RegisterModelValidator : AbstractValidator<RegisterModel>
{
public RegisterModelValidator()
{
RuleFor(x => x.Email).NotEmpty().EmailAddress();
RuleFor(x => x.Password).MinimumLength(6);
}
}
Integrating Validators with Blazor Forms
Use the FluentValidationValidator
component inside your EditForm
:
<EditForm Model="model" OnValidSubmit="HandleValidSubmit">
<FluentValidationValidator />
<InputText @bind-Value="model.Email" />
<ValidationMessage For="@(() => model.Email)" />
<!-- More fields -->
<button type="submit">Submit</button>
</EditForm>
This automatically hooks the validator to the form.
Advanced Validation Scenarios
FluentValidation shines in complex rules:
RuleFor(x => x.Password)
.NotEmpty()
.MinimumLength(8)
.When(x => x.RequiresStrongPassword);
You can also define rule sets and nested validators for hierarchical data models.
Enhancing User Experience with Real-Time Feedback
Displaying Validation Errors Dynamically
Blazor re-renders components reactively, making it easy to display error messages as users type. Just include <ValidationMessage>
per field.
Customizing UI Based on Validation State
You can bind CSS classes conditionally:
<InputText @bind-Value="model.Email" class="@(IsValid(nameof(model.Email)) ? "valid" : "invalid")" />
Use helper methods or validation state checks to drive visual cues like icons or border colors.
Best Practices and Performance Tips
Keeping Validators Maintainable
- Use descriptive rule chains
- Group rules logically with comments or regions
- Use extension methods for shared rules
Validating Nested Objects and Collections
FluentValidation supports .SetValidator()
for nested models:
RuleFor(x => x.Address).SetValidator(new AddressValidator());
Performance Considerations
- Avoid validating on every keystroke for large forms
- Validate on blur or submit for better performance
- Use debouncing if real-time validation is essential
FAQ: Common Questions About FluentValidation in Blazor
Yes, but it’s best to pick one for consistency.
Override messages or use WithMessage(localizer["Key"])
.
Yes, it’s compatible with both hosting models.
Conclusion: Stop Fighting Forms and Start Writing Code
Blazor’s forms don’t have to be a pain. With FluentValidation, you gain cleaner code, more control, and happier users. The setup is simple, the rules are powerful, and the result is a better developer experience.
Give FluentValidation a try in your next Blazor form. You might just wonder why you didn’t do it sooner.