La gestione degli errori imprevisti sulla parte front end di un’applicazione web può essere noioso e bloccante per l’utente. Per questo motivo possiamo usare l’elemento <ErrorBoundary> per visualizzare un messaggio di errore. Vediamo insieme come utilizzarlo passo per passo.
Creiamo il progetto in Visual Studio
Creiamo un nuovo progetto in Visual Studio

scegliamo un progetto Blazor Server (ma gli stessi concetti valgono anche per Blazor WebAssembly)

e poi scegliamo il nome del progetto. ErrorBoudaryExample può fare al caso nostro.

Il passo successivo ci chiede qualche informazione aggiuntiva ma lasciamo tutto così com’è.

A questo punto il nostro progetto di esempio è pronto per essere modificato.
Generiamo un’eccezione
Per poter vedere esattamente cosa succede con un errore imprevisto, cerchiamo di simularlo tramite un semplice bottone che solleva una exception. Nella directory Shared e modifichiamo il componente SurveyPrompt.razor inserendo questo codice nella sezione @code:
private void ButtonErrorGenerator()
{
throw new Exception("Ho generato un problema serio");
}
e di conseguenza il suo bottone nella zona di markup
<button @onclick="ButtonErrorGenerator" >Genera errore</button>
A questo punto facciamo partire il nostro progetto con il tasto F5. Dopo qualche istante apparirà la nostra pagina con il nostro bel bottone. Non appena cliccheremo su di esso, ci apparirà quella tristissima banda giallognola in basso che ci avvisa di un errore irreversibile

Pur restando parzialmente funzionante, il nostro sito avrà questa barra di errore visibile finché non cliccheremo sulla X a destra. In ogni caso nessuna informazione sull’errore ci viene fornita.
Usiamo l’ErrorBoudary
A questo punto iniziamo a togliere quell’odiosa barra giallina in basso con l’inserimento di un tag <ErrorBoundary> attorno alla direttiva @Body in MainLayout.razor che si trova sempre nella cartella Shared. In questo modo andremo a wrappare qualunque errore non gestito del nostro front end.
Non appena cliccheremo sul bottone, il debugger si fermerà sull’eccezione

ma noi temerari premeremo ancora F5 per insistere e far continuare l’esecuzione.

Splendido! Siamo passati dalla barra giallina in basso ad una barra rossa in mezzo allo schermo! Anche se preferisco il rosso, non è ancora il massimo della vita. Anche perché non mi da assolutamente nessuna informazione sull’errore.
Qualche info in più
Vediamo quindi come arricchire le informazioni da fornire all’utente in merito all’errore. Andando a guardare la classe ErrorBoundary, ci accorgiamo che deriva da una classe base ErrorBoudaryBase la quale contiene un ChildContent:
namespace Microsoft.AspNetCore.Components.Web
{
public class ErrorBoundary : ErrorBoundaryBase
{
public ErrorBoundary();
protected override void BuildRenderTree(RenderTreeBuilder builder);
[AsyncStateMachine(typeof(<OnErrorAsync>d__4))]
protected override Task OnErrorAsync(Exception exception);
}
}
namespace Microsoft.AspNetCore.Components
{
public abstract class ErrorBoundaryBase : ComponentBase, IErrorBoundary
{
[Parameter]
public RenderFragment? ChildContent
{
get
{
throw null;
}
set
{
throw null;
}
}
[Parameter]
public RenderFragment<Exception>? ErrorContent
{
[CompilerGenerated]
get
{
throw null;
}
[CompilerGenerated]
set
{
throw null;
}
}
[Parameter]
public int MaximumErrorCount
{
[CompilerGenerated]
get
{
throw null;
}
[CompilerGenerated]
set
{
throw null;
}
}
protected Exception? CurrentException
{
[CompilerGenerated]
get
{
throw null;
}
}
public void Recover()
{
throw null;
}
protected abstract Task OnErrorAsync(Exception exception);
void IErrorBoundary.HandleException(Exception exception)
{
throw null;
}
protected ErrorBoundaryBase()
{
throw null;
}
}
}
Il ChildContent è utilizzato dal nostro componente per essere renderizzato, e troviamo anche una proprietà RenderFragment chiamata ErrorContent che possiamo utilizzare per visualizzare alcune informazioni utili alla decifrazione del nostro errore. Possiamo, ad esempio, utilizzare queste sezioni in questo modo:
<article class="content px-4">
<ErrorBoundary>
<ChildContent>
@Body
</ChildContent>
<ErrorContent Context="ex">
<p class="custom-error">@ex.Message</p>
</ErrorContent>
</ErrorBoundary>
</article>
Come potete notare, all’interno del tag <ErrorContent> c’è la vera gestione dell’errore che mostrerà a video il messaggio generato dall’exception. Avendo a disposizione la classe Exception nella sua interezza, posiamo recuperare tutte le informazioni che vogliamo. Teniamo però presente che se inseriamo le informazioni di StackTrace e le rendiamo disponibili all’utente, egli sarà ancora più confuso data la complessità e la verbosità di questa informazione. Ottimo dare l’idea di quale errore è capitato, ma non entrerei nei dettagli. Almeno per gli utenti finali.
Dunque, l’output sarà ora il seguente:

Ed ecco che ci siamo tolti tutti i box con i colori più assurdi e scriviamo a video il testo dell’errore. Ovviamente ora con il CSS possiamo giocare con tutti i colori che vogliamo per rendere più gradevole, accattivante, attrattivo o inutile il nostro messaggio. Ma questa volta dipenderà solo da noi.
Resuscitare l’applicazione
Dopo aver generato un errore di questo tipo, la nostra applicazione è bloccata. Questo potrebbe essere voluto oppure potrebbe essere necessario far ripartire la nostra applicazione.
L’ErrorBoudary mette a disposizione il metodo “Recover” per far ripartire l’applicazione dopo l’errore. Per poterlo usare dovremmo fare un paio di modifiche al nostro codice.
Per prima cosa dovremmo creare un riferimento all’ErrorBoundary in questo modo
<ErrorBoundary @ref="errorBoundary">
e di conseguenza il suo corrispondente nel codice C#
private ErrorBoundary errorBoundary;
Quindi nell’override del metodo di OnParameterSet() richiameremo il metodo Recover
protected override void OnParametersSet()
{
errorBoundary?.Recover();
}
In questo modo l’applicazione continuerà a funzionare.
Personalmente non amo molto questa pratica in quanto gli errori dovrebbero essere gestiti diversamente. Questo rimarrebbe l’ultimo baluardo a fronte di un errore imprevisto. E se l’errore non è previsto, è corretto che l’applicazione non possa continuare. Ma questa è un’opinione personale.
Il codice usato per questo articolo lo trovate qui.
Alla prossima!