Come sappiamo, Blazor supporta nativamente le data annotation per la validazione dei dati in input: grazie a questa funzionalità, possiamo per esempio decorare una classe User con attributi che ne specifichino i requisiti formali:
public class User { [Required] public string Username { get; set; } [RegularExpression(Constants.UK_PHONE_NUMBER)] public string MobilePhone { get; set; } [RegularExpression(Constants.UK_PHONE_NUMBER)] public string LandLinePhone { get; set; } }
A questo punto, è sufficiente aggiungere un DataAnnotationValidator (e magari anche un ValidationSummary) al componente EditForm, e il motore di rendering si occuperà automaticamente di verificarne la correttezza prima di procedere al submit:
<EditForm Model="this.NewUser" OnValidSubmit="this.SubmitAsync" class="col-6"> <DataAnnotationsValidator /> <ValidationSummary /> <div class="form-group"> <label>Username</label> <InputText class="form-control" @bind-Value="this.NewUser.Username" /> </div> <div class="form-group"> <label>Mobile Phone</label> <InputText class="form-control" @bind-Value="this.NewUser.MobilePhone" /> </div> <div class="form-group"> <label>Landline phone</label> <InputText class="form-control" @bind-Value="this.NewUser.LandLinePhone" /> </div> <button type="submit" class="btn btn-primary">Save</button> </EditForm> @Code { public User NewUser { get; set; } public async Task SubmitAsync() { // .. logica per memorizzare l'utente qui ... } }
Nel nostro caso, se provassimo a salvare uno user con dati errati, gli errori ci verrebbero evidenziati come in figura.

Purtroppo le data annotation funzionano bene con regole semplici, ma non sono idonee a rappresentare logiche di validazione più complesse, per esempio quelle che coinvolgono diverse proprietà.
Per questi scopi, una delle possibili soluzioni in Blazor è quella di costruire un custom validator. Immaginiamo di voler far sì che almeno uno tra Mobile Phone e Landline Phone sia obbligatorio. Possiamo implementare questa logica in una classe UserPhoneValidator simile alla seguente:
public class UserPhoneValidator : ComponentBase { private ValidationMessageStore _store; [CascadingParameter] public EditContext Context { get; set; } protected override void OnInitialized() { base.OnInitialized(); _store = new ValidationMessageStore(this.Context); this.Context.OnValidationRequested += Context_OnValidationRequested; ; this.Context.OnFieldChanged += Context_OnFieldChanged; } private void Context_OnValidationRequested(object sender, ValidationRequestedEventArgs e) { this.ExecuteValidation(); } private void Context_OnFieldChanged(object sender, FieldChangedEventArgs e) { if (e.FieldIdentifier.FieldName == "MobilePhone" || e.FieldIdentifier.FieldName == "LandLinePhone") { this.ExecuteValidation(); } } // .. altro codice qui .. }
La nostra classe eredita da ComponentBase, così che possiamo utilizzarla nel markup di Blazor, ed espone una proprietà di tipo EditContext. Si tratta di un CascadingParameter che viene automaticamente assegnato dalla form all'interno della quale poniamo il nostro componente, così che possiamo sia accederne al contenuto, sia ricevere una notifica al verificarsi di alcuni eventi.
Nel nostro caso, abbiamo sottoscritto gli eventi OnValidationRequested e OnFieldChanged, per eseguire la nostra logica sia al submit della form stessa, sia quando il valore di un field viene modificato. In quest'ultimo caso, come possiamo notare, ci preoccupiamo solo dei field relativi ai due numeri di telefono che vogliamo monitorare.
Il codice di ExecuteValidation è abbastanza semplice e sfrutta un ValidationMessageStore per inviare gli esiti della validazione alla form:
private void ExecuteValidation() { var model = (this.Context.Model as User); if (model == null) return; // this only works with User objects _store.Clear(); if (string.IsNullOrWhiteSpace(model.MobilePhone) && string.IsNullOrWhiteSpace(model.LandLinePhone)) { _store.Add(() => model.MobilePhone, "Either mobile or landline phone must be provided"); _store.Add(() => model.LandLinePhone, "Either mobile or landline phone must be provided"); } }
Come primo passo, puliamo lo store da eventuali messaggi precedenti. Poi, se entrambi i numeri di telefono sono vuoti, aggiungiamo una entry per ciascuno di queste due proprietà.
L'ultimo aspetto da non dimenticare è quello di implementare IDisposable, come in tutti i casi in cui sottoscriviamo eventi, per evitare memory leak:
public class UserPhoneValidator : ComponentBase, IDisposable { // .. altro codice qui .. public void Dispose() { this.Context.OnValidationRequested -= Context_OnValidationRequested; ; this.Context.OnFieldChanged -= Context_OnFieldChanged; } }
A questo punto, possiamo finalmente aggiungere il nostro validatore alla form in pagina:
<EditForm Model="this.NewUser" OnValidSubmit="this.Submit" class="col-6"> <DataAnnotationsValidator /> <UserPhoneValidator /> <ValidationSummary /> ... <button type="submit" class="btn btn-primary">Save</button> </EditForm>
Se abbiamo svolto tutti i passaggi correttamente, vedremo il messaggio di errore apparire contemporaneamente su entrambe le proprietà nel caso siano tutte e due vuote, e sparire nel momento in cui ne valorizziamo una.

Commenti
Per inserire un commento, devi avere un account.
Fai il login e torna a questa pagina, oppure registrati alla nostra community.
Approfondimenti
Blazor <3 Javascript
Blazor: WebAssembly
Aggiornare la query string inserendo dei parametri in ReactJS
Le novità di ASP.NET Core 5
Sviluppare codice nativo per Windows e Linux con .NET Core
Messaggi in tempo reale con Blazor Server
Caricare le immagini di una pagina in lazy loading con Angular
Sfruttare al massimo Kubernetes con Azure DevOps
Pubblicare un'applicazione come singolo eseguibile con .NET Core 3
Effettuare il multibinding in un'applicazione Xamarin Forms
Tra pochi minuti inizia #aspilive Re|Build 2020!Seguici comodamente: tutte le novità per lo sviluppo di casa Microsoft: C# 9, #net5, #azure, #maui, #blazor, #VSCode, #WSL2 e tanto altro! Iscrizioni e live dalle 14 su https://aspit.co/ReBuild-20
Le novità di C# 9
I più letti di oggi
- Modificare la modalità di esecuzione delle query con Include in Entity Framework Core 5
- Effettuare l'upload di un file da Blazor su Azure Blob Storage
- ecco tutte le novità pubblicate sui nostri siti questa settimana: https://aspit.co/wkly buon week-end!
- ecco tutte le novità pubblicate sui nostri siti questa settimana: https://aspit.co/wkly buon week-end!
- Creare un web server locale con LiveReload
- Le novità di Entity Framework Core 5