In passato abbiamo visto come poter eseguire validazioni complesse in Blazor tramite la realizzazione di un custom validator (https://www.aspitalia.com/script/1362/Implementare-Logiche-Validazione-Complesse-EditForm-Blazor.aspx). Purtroppo questo sistema di validazione soffre di un grosso limite: l'esecuzione è sincrona e, pertanto, non è facile iniettare logiche che invece richiedano l'utilizzo di async/await, come per esempio una chiamata lato server o a un servizio esterno.
Uno dei modi che abbiamo a disposizione è quello di utilizzare una logica leggermente differente, evitando che sia la form a invocare la validazione e richiamandola esplicitamente durante la fase di submit.
Cerchiamo di capire meglio questo procedimento con un esempio che coinvolge la stessa classe User che abbiamo usato in passato. L'idea iniziale è quella di utilizzare l'event handler OnSubmit invece che OnValidSubmit (che come abbiamo visto, richiama autonomamente una validazione sincrona):
<EditForm EditContext="@_editContext" OnSubmit="this.SubmitAsync"> ... </EditForm> @code { // oggetto in binding con la form private User NewUser { get; set; } = new User(); // edit context che collega lo User alla form private EditContext _editContext; private ValidationMessageStore _store; protected override void OnInitialized() { // inizializzo l'EditContext this.RefreshEditContext(); } private void RefreshEditContext() { _editContext = new EditContext(this.NewUser); _store = new ValidationMessageStore(_editContext); } public async Task SubmitAsync() { _store.Clear(); if (_editContext.Validate() && await this.ValidateServerSideAsync()) { await SaveUser(); this.NewUser = new User(); this.RefreshContext(); } } }
Ci sono diversi aspetti d'interesse nel codice in alto. Innanzi tutto, visto che l'unico modo per scatenare la validazione della form da codice è tramite il suo EditContext, dobbiamo effettuare il binding della relativa proprietà della form con un field _editContext. Quest'ultimo va opportunamente inizializzato sia durante OnInitialized che ogni volta che l'istanza di User cambia - per esempio dopo aver salvato.
Insieme all'EditContext, abbiamo anche bisogno di un ValidationMessageStore, che sfrutteremo per iniettare nella form eventuali messaggi di errore che provengono dalla nostra logica custom.
Quando il metodo SubmitAsync viene invocato, per prima cosa svuotiamo lo store da eventuali errori già restituiti in precedenza, perché l'utente potrebbe aver modificato il valore dei campi, che quindi vanno rivalutati. In seguito, invochiamo sia il metodo (sincrono) Validate, che valuterà la correttezza della entity in base alle data annotation, che il nostro ValidateServerSideAsync, che invece effettuerà la chiamata lato server, per esempio per verificare che il nome utente non sia già utilizzato.
Anche il contenuto di quest'ultimo metodo è interessante:
private async Task<bool> ValidateServerSideAsync() { if (await userService.CheckExists(this.NewUser.Username)) { _store.Add(() => this.NewUser.Username, "Username already exists"); _editContext.NotifyValidationStateChanged(); return false; } return true; }
Nel caso in cui il nome utente non sia valido, aggiungiamo l'errore allo store. Visto che questo codice viene eseguito al di fuori della Validate standard della form, e per giunta in maniera asincrona, dobbiamo anche segnalare che lo stato della validazione è potenzialmente cambiato tramite NotifyValidationStateChanged.
Un'ultima nota riguarda il fatto che, durante queste operazioni che potenzialmente potrebbero durare alcuni secondi, non c'è nulla che impedisca all'utente di premere diverse volte il pulsante Submit. Quindi è fondamentale utilizzare una tecnica come quella descritta nello script precedente (https://www.aspitalia.com/script/1363/Disabilitare-Pulsante-Blazor-Salvataggio.aspx) per disabilitarlo durante il salvataggio.
Nel prossimo script vedremo come implementare questa funzionalità tramite un componente ad-hoc.
Commenti
Per inserire un commento, devi avere un account.
Fai il login e torna a questa pagina, oppure registrati alla nostra community.
Approfondimenti
Sfruttare MQTT in cloud e in edge con Azure Event Grid
Utilizzare Model as a Service su Microsoft Azure
Paginare i risultati con QuickGrid in Blazor
Eseguire attività con Azure Container Jobs
Recuperare un elemento inserito nella cache del browser tramite API JavaScript
Implementare l'infinite scroll con QuickGrid in Blazor Server
Effettuare lo stream della risposta in ASP.NET Core tramite IAsyncEnumerable
Hosting di componenti WebAssembly in un'applicazione Blazor static
Elencare le container images installate in un cluster di Kubernetes
Eseguire query manipolando liste di tipi semplici con Entity Framework Core
Evitare il flickering dei componenti nel prerender di Blazor 8
Creare form tipizzati con Angular
I più letti di oggi
- Utilizzare Docker Compose con Azure App Service
- Utilizzare QuickGrid di Blazor con Entity Framework
- Modernizzare le applicazioni WPF e Windows Forms con Blazor
- ASP 3 per esempi
- annunciato #netstandard 2.1. .NET Core lo supporterà a partire da #netcore3, così come le prossime versione di #xamarin, #mono e #unity.il supporto per #netfx 4.8, invece, non ci sarà. https://aspit.co/bq2
- Steel Style CheckBox per Silverlight 4.0