In this article, we will talk about Fluent Validation and it’s implementation in ASP.NET Core Applications. We will discuss the preferred alternative to Data Annotations and implement it in an ASP.Net core API. Traditionally, most validation in .NET is done using Data Annotations. There are a few issues with the old approach:
- Our model can get “bloated”
- Extensibility is limited
- Testing isn’t the nicest experience
To address some of these concerns, instead, we’re going to utilize a .NET library called FluentValidation to perform validation for our classes.
FluentValidation?
FluentValidation is a validation library for .NET used for building strongly type validation rules for your business objects. Fluent validations uses lambda expressions to build validation rules. FluentValidation supports integration with ASP.NET Core 2.1 or 3.1 (3.1 recommended).
To enable MVC integration, you’ll need to add a reference to the FluentValidation.AspNetCore assembly by installing the appropriate NuGet package. From the command line, you can install the package by the following command:
> dotnet add package FluentValidation.AspNetCore
Configuring FluentValidation: Once installed, you’ll need to configure FluentValidation in your app’s Startup class by calling the AddFluentValidation extension method inside the ConfigureServices method.
In order to discover your validators, they must be registered with the services collection.
services.AddTransient<IValidator<TestModel>, TestModelValidator>();
For registering Validator, there are three ways -
- Registering each validator in Service with AddTransient (above example).
- Registering using “RegisterValidatorsFromAssemblyContaining” method registers all validators derived from AbstractValidator class within the assembly containing the specified type.
- Registering using “RegisterValidatorsFromAssembly” method.
public class TestModel {
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
}
public class TestModelValidator : AbstractValidator<TestModel> {
public TestModelValidator() {
RuleFor(x => x.Id).NotNull();
RuleFor(x => x.Name).Length(0, 10);
RuleFor(x => x.Age).InclusiveBetween(18, 60);
}
}
Now when you post the form, MVC’s model-binding infrastructure will validate the TestModel object with the TestModelValidator, and add the validation results to ModelState.
public class ExampleController : Controller {
public ActionResult Create() {
return View();
}
[HttpPost]
public IActionResult Create(TestModel model) {
// re-render the view when validation failed.
if(! ModelState.IsValid) {
return View("Create", person);
}
return RedirectToAction("Index");
}
}
Manual validation:
There can be a case where you need to validate an object manually within your application using Fluent Validation.
IValidator<TestModel> _validator = new ObjAValidation();
var result = validator.Validate(objTestModel);
In Unit tests, you can setup the Validate method of IValidator with Moq in following way:
Mock<IValidator<TestModel>> _mockValidator = new Mock<IValidator<TestModel>>();
_mockValidator.Setup(x => x.Validate(new TestModel()));
FluentValidation provides a great alternative to Data Annotations in order to validate our models. FluentValidation integration and validation rules are easy to read, easy to use and easy to test.