I ran into an interesting scenario the other day whilst using a 3rd party library to plot some grids. I accidentally discovered an edge case which raised an exception in the library in specific scenarios. No problem, normally if the issue is intermittent/unknown one could just wrap up the problematic code in try catch until you’ve figured out the issue. I then discovered that Blazor doesn’t have a like-for-like try catch block for handling errors while rendering components which led me to today’s discussion on error handling in Blazor.

The Error Boundary Component

Microsoft has done us a solid and actually provided something for us, the ErrorBoundary component. Let’s spin up a new Blazor server with dotnet new blazorserver to see this in action. First, we’ll raise an exception on the counter page i.e.

@code {
    private int currentCount = 0;

    private void IncrementCount()
    {
        throw new Exception("The system is offline");
    }
}

At this point, hitting the Click Me button would create the dreaded error UI ribbon.

The ErrorBoundary component can be placed somewhere central like the main layout to ensure errors are handled. The code below is an example of how you might handle a scenario like this.

<article class="content px-4">
    <ErrorBoundary>
        <ChildContent>
                @Body
            </ChildContent>
            <ErrorContent>
                <p class="errorUI">Well...this is awkward</p>
            </ErrorContent>    
    </ErrorBoundary>
</article>

Clicking on Click Me results in the following message to be displayed without the error ribbon at the bottom of the screen.

Some notes

Important to note in the above example is that the exception is still considered unhandled. Don’t consider this a free pass to never deal with exceptions! Additionally, Microsoft suggests that narrow scoping of the error boundaries is advisable. As an example, let’s add in a component called MyComponent which is added to the DOM when the Click Me to Add MyComponent is clicked. The component will raise an exception on initialization and we’ll catch this with an Error boundary. The code for this is shown below.

Adding MyComponent

<h3>Hello World</h3>

@code {
    protected override void OnInitialized()
    {
        throw new Exception("Test exception");
    }
}

Adding new Button to Counter Page

@page "/counter"

<PageTitle>Counter</PageTitle>

<h1>Counter</h1>

<p role="status">Current count: @currentCount</p>

<div>
    <button class="btn btn-primary" @onclick="IncrementCount">Click me</button>    
</div>
<div class="mt-3">
    @if (_loaded)
    {
        
        <ErrorBoundary>
            <ChildContent>
                <MyComponent/>
            </ChildContent>
            <ErrorContent>
                <p>MyComponent failed to load</p>
            </ErrorContent>    
        </ErrorBoundary>
    }

    <button class="btn btn-primary" @onclick="AddMyComponent">Click me to Add MyComponent</button>
    
</div>

@code {
    private int currentCount = 0;

    private bool _loaded = false;
    private void IncrementCount()
    {
        throw new Exception("The system is offline");
    }

    private void AddMyComponent()
    {
        _loaded = true;
        StateHasChanged();
    }

}

Testing this out you should now see the error boundary being hit when you click on the new button.

Wrapping up

And that’s it! Feel free to take a look at the documentation has written up on additional cases for error handling. All code from today’s article can be found on my Github repo.

Until next time :)