Introduzione
Nel precedente articolo, abbiamo esplorato come implementare il modello CQRS con MediatR in ASP.NET Core. Abbiamo creato comandi, query e gestori per separare le responsabilità di lettura e scrittura. In questo articolo, continueremo su quella base e vedremo come integrare FluentValidation per garantire che i dati siano validati correttamente prima di essere elaborati.
Cos'è FluentValidation ?
FluentValidation è una libreria .NET popolare e potente che consente di definire regole di validazione per i tuoi modelli in modo semplice e dichiarativo. Con FluentValidation, puoi separare la logica di validazione dal tuo codice principale, rendendolo più pulito e manutenibile.
Implementazione
Per cominciare, dobbiamo scaricare il codice sorgente dell’articolo precedente, che è disponibile a questo indirizzo: CQRSExample.NET su GitHub. Questo progetto contiene una configurazione di base per ASP.NET Core con CQRS e MediatR.
CQRSExample.NET
git clone https://github.com/irimescucosmin/CQRSExample.NET.git
Installazione FluentValidation
Una volta scaricato il progetto e aperto con il nostro IDE preferito, possiamo procedere con l’installazione dei pacchetti NuGet necessari per l’implementazione di FluentValidation:
Install-Package FluentValidation
Install-Package FluentValidation.AspNetCore
ValidationBehavior
Per evitare di richiamare i validatori all’interno del handler di ogni feature, possiamo definire una pipeline per MediatR che si occuperà di eseguire la validazione automaticamente. Questo approccio centralizza la logica di validazione e rende il codice più pulito e manutenibile.
Definisci una nuova classe ValidationBehavior
che implementa IPipelineBehavior<TRequest, TResponse>
.
using FluentValidation;
using MediatR;
namespace CQRSExample.NET.Behaviors;
public class ValidationBehavior(IEnumerable> validators) : IPipelineBehavior
where TRequest : IRequest
{
public async Task Handle(TRequest request, RequestHandlerDelegate next, CancellationToken cancellationToken)
{
var context = new ValidationContext(request);
var failures = validators
.Select(v => v.Validate(context))
.SelectMany(result => result.Errors)
.Where(f => f != null)
.ToList();
if (failures.Count != 0)
{
throw new ValidationException(failures);
}
return await next();
}
}
Registrare ValidationBehavior e FluentValidation
Adesso che abbiamo definito il nostro ValidationBehavior
, possiamo procedere con la registrazione di FluentValidation
e della pipeline di validazione nel file Program.cs
.
// Register MediatR
builder.Services.AddMediatR(cfg => cfg.RegisterServicesFromAssemblies(AppDomain.CurrentDomain.GetAssemblies()));
// Register FluentValidation Service
builder.Services.AddValidatorsFromAssembly(typeof(Program).Assembly);
// Register the validation behavior
builder.Services.AddTransient(typeof(IPipelineBehavior<,>), typeof(ValidationBehavior<,>));
Validazione AddUserName
Ora siamo pronti per aggiungere il nostro primo validatore per il comando AddUserName
. Questo garantisce che i dati siano correttamente validati prima di essere elaborati dal handler.
Creiamo una nuova classe nella cartella Features/AddUserName
che estende AbstractValidator<AddUsernameCommand>
e definiamo le regole di validazione.
using CQRSExample.NET.Database;
using CQRSExample.NET.Features.AddUserName;
using FluentValidation;
public class AddUsernameCommandValidator : AbstractValidator
{
public AddUsernameCommandValidator()
{
RuleFor(x => x.UserName).NotEmpty().WithMessage("Username is required.")
.Must(BeUniqueUsername).WithMessage("Username already exists.");
}
private static bool BeUniqueUsername(string username)
{
return !FakeDatabase.UserNames.Contains(username);
}
}
RuleFor(x => x.UserName)
Specifica che la proprietàUserName
del comando deve rispettare le seguenti regole:NotEmpty()
Assicura che il campo non sia vuoto, fornendo un messaggio di errore personalizzato.Must(BeUniqueUsername)
Verifica che ilUsername
sia unico utilizzando una funzione personalizzataBeUniqueUsername
, che controlla se il nome utente è già presente nel database fittizio.
Conclusione
Siamo arrivati alla fine! Ora possiamo avviare la nostra applicazione e provare le API utilizzando Swagger. Una volta avviata l’applicazione, apri il browser e visita l’URL del tuo servizio seguito da /swagger
, ad esempio http://localhost:5000/swagger. Questo ti porterà all’interfaccia di Swagger, dove potrai esplorare e testare facilmente i tuoi endpoint API.
Grazie all’integrazione di FluentValidation, CQRS e MediatR, la nostra applicazione è ora robusta e ben strutturata, pronta per essere scalata e mantenuta nel tempo. Buon lavoro!
FAQ
FluentValidation è una libreria .NET per la validazione di oggetti di business. Utilizza un’API fluente per definire le regole di validazione.
CQRS (Command Query Responsibility Segregation) è un pattern architetturale che separa le operazioni di lettura (Query) dalle operazioni di scrittura (Command), migliorando la scalabilità e la manutenibilità dell’applicazione.
MediatR è una libreria .NET che implementa il pattern Mediator, permettendo la comunicazione tra componenti senza che questi siano direttamente accoppiati.
Sì, FluentValidation può essere utilizzato indipendentemente da CQRS. Può essere integrato in qualsiasi applicazione .NET per validare oggetti di business, controller MVC, e altro.