Explaining ASP.NET Core Using FluentValidation: A Step-by-Step Guide for Beginners
Introduction
ASP.NET Core is a powerful and flexible framework for building modern, cloud-ready, Internet-connected applications. Among its many features, data validation is crucial for ensuring data integrity and security. One of the most popular libraries for implementing data validation in ASP.NET Core is FluentValidation. FluentValidation is a lightweight, unobtrusive, and highly testable validation library for .NET. It allows developers to define validation rules using a fluent interface, making it easier to maintain and extend.
In this guide, we will explore how to integrate FluentValidation into an ASP.NET Core application, configure it, and write validation rules for models.
Prerequisites
Before we dive into FluentValidation, make sure you have the following:
- Basic knowledge of C# and ASP.NET Core.
- Visual Studio or Visual Studio Code installed on your machine.
- .NET SDK installed.
Setup ASP.NET Core Project
Create an ASP.NET Core Web Application:
Open Visual Studio or Visual Studio Code and create a new ASP.NET Core Web Application. Choose the "API" project template for simplicity.
dotnet new webapi -n FluentValidationDemo cd FluentValidationDemo dotnet restore
Add FluentValidation NuGet Package:
To use FluentValidation, you need to add the
FluentValidation.AspNetCore
package to your project. You can do this using the NuGet Package Manager in Visual Studio or the command line.dotnet add package FluentValidation.AspNetCore
Register FluentValidation in Services
Open
Program.cs
:In .NET 6 and later, the
Startup.cs
is integrated intoProgram.cs
. You need to configure services and middleware here.var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddControllers(); // Add FluentValidation services to the container. builder.Services.AddFluentValidation(options => { options.RegisterValidatorsFromAssemblyContaining<Program>(); }); var app = builder.Build(); // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseHttpsRedirection(); app.UseAuthorization(); app.MapControllers(); app.Run();
Create a Model:
For demonstration purposes, let's create a simple
Person
model.public class Person { public string FirstName { get; set; } public string LastName { get; set; } public int Age { get; set; } }
Create a Validator:
Next, you need to create a validator class for the
Person
model. The validator class should inherit fromAbstractValidator<T>
whereT
is the type you want to validate.using FluentValidation; public class PersonValidator : AbstractValidator<Person> { public PersonValidator() { RuleFor(person => person.FirstName) .NotEmpty().WithMessage("First Name is required.") .MinimumLength(2).WithMessage("First Name must be at least 2 characters.") .MaximumLength(50).WithMessage("First Name cannot exceed 50 characters."); RuleFor(person => person.LastName) .NotEmpty().WithMessage("Last Name is required.") .MinimumLength(2).WithMessage("Last Name must be at least 2 characters.") .MaximumLength(50).WithMessage("Last Name cannot exceed 50 characters."); RuleFor(person => person.Age) .NotEmpty().WithMessage("Age is required.") .InclusiveBetween(18, 120).WithMessage("Age must be between 18 and 120."); } }
Register Validator:
In the
Program.cs
, the FluentValidation'sRegisterValidatorsFromAssemblyContaining<Program>();
method automatically registers all validators in the assembly that contains theProgram
class. If your validator is in a different assembly, you can specify it accordingly.
Configure API Controller
Create a Controller:
Create a new controller that will handle HTTP requests and use the
Person
model.using Microsoft.AspNetCore.Mvc; [ApiController] [Route("api/[controller]")] public class PersonsController : ControllerBase { private readonly ILogger<PersonsController> _logger; public PersonsController(ILogger<PersonsController> logger) { _logger = logger; } [HttpPost] public IActionResult Create(Person person) { if (!ModelState.IsValid) { _logger.LogWarning("Invalid Person object received"); return ValidationProblem(ModelState); } // Process the valid Person object _logger.LogInformation("Person object processed successfully"); return Ok(person); } }
Testing the API
Run the Application:
Use Visual Studio or Visual Studio Code to run the application.
dotnet run
Test the API Endpoint:
You can use tools like Postman or Swagger UI to test the API endpoint.
Valid Request:
{ "FirstName": "John", "LastName": "Doe", "Age": 30 }
Response:
{ "firstName": "John", "lastName": "Doe", "age": 30 }
Invalid Request:
{ "FirstName": "", "LastName": "Doe", "Age": 17 }
Response:
{ "type": "https://tools.ietf.org/html/rfc7231#section-6.5.1", "title": "One or more validation errors occurred.", "status": 400, "traceId": "|c42f61a6-4fbd8420c37c4f60.", "errors": { "Age": [ "Age must be between 18 and 120." ], "FirstName": [ "First Name is required.", "First Name must be at least 2 characters." ] } }
Advanced Topics
Custom Validators:
You can create custom validators to handle more complex validation scenarios. Here's an example of a custom validator that checks if a person is a minor.
public class NotMinorValidator : PropertyValidator<Person, int> { public NotMinorValidator() : base("The age must be at least 18.") { } protected override bool IsValid(PropertyValidatorContext context) { return context.PropertyValue >= 18; } }
Use the custom validator in your
PersonValidator
class:RuleFor(person => person.Age) .SetValidator(new NotMinorValidator());
Conditional Validation:
FluentValidation supports conditional validation. For example, you can validate a field only if another field meets a certain condition.
RuleFor(person => person.Age) .NotEmpty().When(person => !string.IsNullOrEmpty(person.FirstName)) .WithMessage("Age is required when First Name is provided.");
Global Customizations:
You can configure global settings for FluentValidation, such as custom message placeholders or validation failure messages.
builder.Services.AddFluentValidation(options => { options.RegisterValidatorsFromAssemblyContaining<Program>(); options.GlobalDefaultMessageFormatter.AppendArgumentNameToPropertyName = false; options.ImplicitlyValidateChildProperties = true; options.CascadeMode = CascadeMode.StopOnFirstFailure; });
Conclusion
FluentValidation is a powerful and flexible library for implementing data validation in ASP.NET Core applications. In this guide, we covered the basics of integrating FluentValidation into an ASP.NET Core project, creating models and validators, and configuring the application to use the validators. By leveraging FluentValidation's fluent API and advanced features, you can create robust and maintainable validation logic in your ASP.NET Core applications. Happy coding!