Nello scorso script (https://www.aspitalia.com/script/1312/Utilizzare-Framework-FluentValidation-ASP.NET-Core.aspx) ci siamo occupati di FluentValidation con ASP .NET Core e di come validare i dati lato server. FluentValidation permette di implementare anche scenari più complessi, fornendo anche alcuni strumenti utili per il testing dei nostri validatori.
Scrivere un validatore complesso
Partendo dall'esempio mostrato nello script precedente, facciamo evolvere il validatore Person con alcune logiche complesse. Abbiamo quindi inserito delle regole di validazione che accorpano più regole che afferiscono a validazioni di indirizzi mail e numeri telefonici.public class PersonValidator : AbstractValidator<PersonViewModel> { // .. altro codice qui .. // Set Rule RuleSet(ValidaMail, () => { RuleFor(x => x.EmailAddress).EmailAddress().NotEmpty(); RuleFor(x => x.PecMail).EmailAddress(); }); // Set Rule RuleSet(ValidaNumeriTelefono, () => { RuleFor(x => x.PhoneNumber).NotEmpty().SetValidator(new InternationalPhoneRule()); }); }
Per richiamare esplicitamente i RuleSet appena dichiarati, è necessario impostare nella CustomizeValidator il set di regole da richiamare in aggiunta alla regola impostata sul ViewModel.
[HttpPost("PersonRule")] public IActionResult PostRule( [CustomizeValidator(RuleSet = Validators.PersonValidator.ValidaNumeriTelefono)] [FromBody] PersonViewModel value) { if (ModelState.IsValid) return Ok(); return BadRequest(ModelState); }
Validatori Personalizzati
In aggiunta è possibile anche specificare dei validatori personalizzati come, ad esempio, InternationalPhoneRule dell'esempio precedente. Un validatore personalizzato quindi ci consente di esprimere logiche complesse sui dati e restituire errori chiari per ogni tipologia di errore. Ecco un esempio:public class InternationalPhoneRule: PropertyValidator { public InternationalPhoneRule() : base("{PropertyName} must contain phone number in format: +IINNN-PPPPPPPP") { } protected override bool IsValid(PropertyValidatorContext context) { bool isValid = false; string phoneNumber = context.PropertyValue as string; if (phoneNumber.StartsWith("+")) { var splitPhone = phoneNumber.Split("-"); if (splitPhone?.Count() != 2) context.MessageFormatter .BuildMessage("{PropertyName} not contains national prefix with separator -"); else isValid = true; } else { context.MessageFormatter .BuildMessage("{PropertyName} not contains international prefix with separator +"); } return isValid; } }
Testing
Una funzionalità molto interessante è la possibilità di testare le proprie logiche di validazione campo per campo verificando così gli errori con più precisione.Nel metodo sottostante, scritto con XUnit, scriviamo un metodo di test che validi il campo Name con il valore null. Il test deve quindi fallire perché abbiamo richiesto l'obbligatorietà del campo e con una stringa di almeno un carattere.
La classe di validazione, attraverso il namespace FluentValidation.TestHelper fornisce una serie di metodi adatti alle classi di testing. In questo caso specifico richiamiamo il metodo ShouldHaveValidationErrorFor che verificherà se la stringa vuota può essere assegnata alla classe. L'esito degli errori di validazione viene inserito in un IEnumerable che ci consente di verificare proprietà per proprietà questo risultato.
[Fact] public void ValidateName() { var errors = _personValidatior.ShouldHaveValidationErrorFor(p => p.Name, null as string); Assert.NotEmpty(errors); string errorCode = errors.ToList().First(x => x.PropertyName == "Name").ErrorCode; Assert.Equal("NotEmptyValidator", errorCode); }
Conclusione
Abbiamo visto alcune funzionalità avanzate di FluentValidation come i RuleSet, i validatori personalizzati e la possibilità di eseguire dei test mirati sul codice.In aggiunta, il framework gestisce gli errori in lingua da specificare in classi apposite.
Il codice esempio che abbiamo descritto in questo script è disponibile al seguente indirizzo: https://github.com/andreatosato/fluentvalidationsample
Commenti
Per inserire un commento, devi avere un account.
Fai il login e torna a questa pagina, oppure registrati alla nostra community.
Approfondimenti
Raggruppare i parametri di una minimal API in un singolo oggetto in ASP.NET Core
Filtrare e rimuovere gli elementi dalla cache del browser tramite le API JavaScript
Recuperare un elemento inserito nella cache del browser tramite API JavaScript
Utilizzare l'attributo autofill del CSS
Determinare lo stato di un pod in Kubernetes
Generare file per il download da Blazor WebAssembly
Sfruttare i tag nell'output cache di ASP.NET Core 7
Bloccare una pull request che arriva da branch non definiti in GitHub
Creare attributi generici in C#
Applicare il versioning ai nostri endpoint ASP.NET Core Minimal API
Gestire undefined e partial nelle reactive forms di Angular
Utilizzare la libreria Benchmark.NET per misurare le performance
I più letti di oggi
- Chiamare direttamente un numero di telefono con HTML5
- ecco tutte le novità pubblicate sui nostri siti questa settimana: https://aspit.co/wkly buon week-end!
- Windows Longhorn Server: anteprima IIS 7.0
- Windows 10 IoT Core e Raspberry Pi 2 con Visual Studio 2015
- Windows Phone 8: le novità per gli sviluppatori - seconda parte
- Produttività con ASP.NET Core 6
- Benvenuto alla giornata
- L'evoluzione del web secondo Microsoft: Silverlight 1.0 e 2.0
- Tutorial Windows Presentation Foundation