Blazor Best Practices: Handling Errors (2022)

Errors are likely to occur, the question is how to handle them. Let’s take a look at best practices in handling them in your Blazor app.

Sooner or later, something is bound to go wrong in your Blazor app.

Be it an unexpected input, an edge case you didn’t preempt, or your web host taking your DB down for maintenance. Errors are likely to occur, the question is how to handle them.

There are a number of factors here, including:

  • How best to handle errors, so users aren’t left staring at a broken screen
  • How to diagnose and fix the problem when something does go wrong
  • Tactics you can use to make sure you’re aware of problems in production
  • Steps you can take to avoid or handle predictable errors

If you’re building Blazor web applications, you have a few options for tackling these challenges. Let’s take a look.

Errors During Development

The first place to catch errors is when you’re building your Blazor app. You’ll see slightly different errors depending on which hosting model you’re using (Server or WASM).

Blazor Server Errors During Development

If your Blazor Server app runs into a problem during development, you’re likely to see a message directing you to the browser console for more details.

Blazor Best Practices: Handling Errors (1)

The console will show you some more details, but if you really want to dig into the problem you’ll want to head over to your server to see more detailed errors.

If you’re running locally using the built-in ASP.NET web server, you’ve most likely got a terminal window open somewhere that looks a bit like this:

Blazor Best Practices: Handling Errors (2)

If you’re using Visual Studio you’ll also find this information reported in the Output > Debug window.

It’s fair to say there’s quite a bit of noise in this window! But if you scroll up to the first reported error you’ll usually find some details which can help track down the problem.

In this case its reporting a System Exception thrown on line 48 of FetchData.razor.

System.Exception: Oof, an error occurred at BestPractices.BlazorServer.Pages.FetchData.OnInitializedAsync() in C:\Users\hilto\RiderProjects\Telerik\BestPractices\BestPractices.BlazorServer\Pages\FetchData.razor:line 48 at Microsoft.AspNetCore.Components.ComponentBase.RunInitAndSetParametersAsync()Microsoft.AspNetCore.Components.Server.Circuits.CircuitHost: Error: Unhandled exception in circuit '9s8O3FNORDmRpW-IDAWcj_20c8obFpFxAaMBzPaH-xg'.

Sure enough, there’s our problem.

(Video) Blazor Global Exception Handling ErrorBoundary

FetchData.razor

...@code { private WeatherForecast[]? forecasts; protected override async Task OnInitializedAsync() { throw new Exception("Oof, an error occurred"); forecasts = await ForecastService.GetForecastAsync(DateTime.Now); }}

Blazor WASM Errors During Development

You’ll see something similar in your Blazor WASM app, albeit with slightly different wording.

An unhandled error has occurred. Reload

Because the Blazor components are running in the browser you’ll automatically see more detailed/directly useful errors in the browser console.

Blazor Best Practices: Handling Errors (3)

In this case, the error is to be found at Index.razor, line 15.

Keeping the Lights On, Using Error Boundaries

If your Blazor Server app throws an error (see above), it effectively blocks your users from continuing, until they reload the app.

Blazor WASM is a little more forgiving and will let you dismiss the error and carry on.

Either way, though, you probably want to provide some more friendly and/or helpful information to your users when something goes wrong.

One way to achieve this is via error boundaries. You can wrap a part of your app in an error boundary, providing a handy way to catch and handle exceptions without bringing your entire application to its knees.

Take this example, where we have a page which renders a ProductDetails component, plus the standard Counter component.

@page "/"<ProductDetails /><Counter />

Here’s how that ProductDetails component looks:

<h3>ProductDetails</h3><button @onclick="BreakMe">Break me!</button>@code { private void BreakMe() { throw new Exception("I'm broken!"); }}

If we run this and click the button we’ll get that standard error bar we saw earlier and, in the case of Blazor Server, our app will end up in a “broken” state, requiring a reload to get back up and running.

To make this experience better for our users we can wrap the ProductDetails component in an ErrorBoundary.

<ErrorBoundary><ProductDetails /></ErrorBoundary>

With this in place, when we click the button, the exception still occurs but is handled, and the default UI for an error boundary is shown (in the same place as the component which has thrown the error).

Blazor Best Practices: Handling Errors (4)

(Video) Global Error Handling in Blazor Apps | Trevoir Williams

The good news is this keeps our app operational, and limits the exception to that one part of the UI. In this example we can still navigate to other pages and/or interact with the counter widget on this page, even in Blazor Server (where this would usually have put the circuit into a broken state and blocked the user from continuing).

By default, the ErrorBoundary component will render a div with the blazor-error-boundary CSS class when an error occurs.

You can override this and provide your own custom UI by defining an ErrorContent property.

<ErrorBoundary> <ChildContent> <ProductDetails/> </ChildContent> <ErrorContent> <div class="border p-4 text-danger"> Sorry about that, something seems to have gone awry. </div> </ErrorContent></ErrorBoundary>

If you want to dig further into error boundaries, check out this helpful post on Working With Unhandled Exceptions by Dave Brock.

Anticipate and Handle Errors

Everything we’ve talked about so far is in the context of unhandled exceptions.

If you choose to handle an exception, you can of course apply whichever logic you deem fit (the user need never know!). So one strategy is to anticipate and handle errors using a standard C# try/catch approach.

For example, in our ProductDetails example, we could try to fetch product details and handle any errors that might occur.

<h3>ProductDetails</h3>@if (loadFailed){ <h2>Something went wrong fetching product details</h2>}<button @onclick="BreakMe">Break me!</button>@code { bool loadFailed = false; private void BreakMe() { try { loadFailed = false; // load product details here throw new Exception("Ooof"); } catch (Exception e) { loadFailed = true; } }}

In practice, you probably don’t want to wrap everything in try/catch blocks and you can always use error boundaries to catch the errors instead.

But, if you have specific exceptions you want to handle, then the humble try/catch is a good option to have.

Retry Network Requests

We tend to assume that networks are reliable, and that a call to a backend API will always work, but in practice transient issues can occur when interacting with servers, and servers can become temporarily unavailable (especially when deployments are being pushed out, or tweaks made to the network which hosts the server).

For these reasons, it pays to assume that your network calls will sometimes fail, especially if you’re building a Blazor WASM app where most of your backend logic lives in a backend Web API.

You could take the brute force approach of manually wrapping every backend call in a try/catch, but this adds a lot of noise to your application and still leaves you facing the question of what to do when a network call does fail.

Instead, for these kinds of transient errors I prefer to use Polly in my Blazor apps.

Polly is an open-source library for defining retry policies and it works nicely with HttpClient to handle transient network failures.

First we need to add a reference to the NuGet package:

(Video) Blazor .NET 6 - Error Boundaries - Custom UI for Errors

Install-Package Microsoft.Extensions.Http.Polly -Version 6.0.7

Then, in our Blazor WASM app we need to tweak Program.cs to use IHttpClientBuilder to register a HttpClient, and specify a retry policy for failed requests.

Program.cs

...builder.Services .AddHttpClient("Default",client => client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress)) .AddTransientHttpErrorPolicy(builder => builder.WaitAndRetryAsync(new[] { TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(5) }));

In this case, should an exception occur when we make a HTTP call, Polly will retry the call twice, once after 1 second, and again after 5. At that point, if the backend call is still throwing exceptions, the exception will be thrown as normal and our app will react accordingly.

Finally we just need to tell our WASM app to use this Default HttpClient when it requests an instance of HttpClient.

builder.Services.AddScoped(sp => sp.GetService<IHttpClientFactory>().CreateClient("Default"));

This is to maintain backwards compatibility. The WASM app will now use our “Default” HttpClient, complete with retry policy, whenever we inject HttpClient into a component.

Diagnose and Fix Errors in Production

When errors occur in production, they can be tricky to pin down; the key is to have enough information to try and understand/fix the problem.

This is where ASP.NET’s built-in logging mechanisms are really useful.

When you run your app (in development or production), you’ve probably noticed all those messages showing up in the console (like the one we explored earlier when we encountered an exception during development).

ASP.NET relies on something called ILogger to log information, warnings and errors to the console by default.

We can also lean on that in production to get detailed error logs when something goes wrong.

The implementation details vary here, depending on your hosting infrastructure and you can choose to store logs in a number of places.

The default logging destinations for Blazor Server are:

  • Console
  • Debug
  • EventSource
  • EventLog (in WIndows)

Blazor WASM, as it runs in the users browser, doesn’t have access to the client’s file system, or network.

Therefore, if you’re logging from Blazor WASM, you’re more limited in terms of where you can send logs, but your app is also likely to be interacting with a backend API which can record its own logs.

With both Server and WASM you can send logs to other destinations via third-party libraries (typically installed via NuGet), such as Elmah, Sentry and Serilog, to name a few.

(Video) Blazor WebAssembly : Global Exception Handling using CascadingValue - EP28

Alternatively, you can go further and plug your app into a third-party Application Performance Management service, such as Azure Application Insights and RayGun, which will often give you much more detailed information about exactly what went wrong, and what else was happening at the time.

However you choose to store them, you’ll want to consider what “level” of log to store.

If you take a look at your appsettings.json file in your Blazor Server app (or backend Web API if you’re using Blazor WASM), you’ll likely see this configuration:

{ "Logging": { "LogLevel": { "Default": "Information", "Microsoft.AspNetCore": "Warning" } }}

This indicates that, in production, the default logging behavior is to record logs at the level of “Information” (and above), except for errors from ASP.NET Core which will only be logged if they are at “Warning” level or above.

If you’re using Blazor WASM you can control this level via Program.cs.

builder.Logging.SetMinimumLevel(LogLevel.Warning);

As well as capturing existing logs, you might want to log additional information from your components. You can do this by injecting an instance of ILogger, then invoking its LogX methods (where X is the level).

ProductDetails.razor

@inject ILogger<ProductDetails> Logger<h3>ProductDetails</h3><button @onclick="BreakMe">Break me!</button>
@code { private void BreakMe() { try { } catch (Exception e) { Logger.LogError("Something went wrong retrieving product details"); } }}

Alerts When Something Goes Wrong

Finally, if you do choose to lean on a third-party library for error logging, you may find they can also raise notifications (for example, via email) when something goes wrong.

If your app is broken, you probably want to know about it! Alert emails are a useful option to make sure you know something’s up.

Tools like Elmah and Serilog, and APMs like RayGun and Application Insights can handle this for you, and also make sure you don’t get flooded with emails when the same error starts recurring more than once.

In Conclusion

Errors are an inevitable part of web development. Blazor, and ASP.NET Core in general, provides several mechanisms to help you handle them.

Error boundaries can contain unhandled exceptions and keep your Blazor Server app running even though one component has failed.

Whether you’re using Blazor WASM or Server, knowing what’s gone wrong in Production or Development is key; use logs to make sure you can dig into the details of any errors which occur.

Consider third-party tools to surface logs and send alert emails when problems occur, and implement a simple retry policy for network requests (so your app can withstand transient network issues).

More Blazor Best Practices: Loading Data

FAQs

How do you handle errors in Blazor? ›

When an error occurs, Blazor apps display a light yellow bar at the bottom of the screen: During development, the bar directs you to the browser console, where you can see the exception. In production, the bar notifies the user that an error has occurred and recommends refreshing the browser.

How do you display error messages in Blazor? ›

How do you display a validation message specific to a field in a Blazor form? You have to use the <ValidationMessage> tag with the “For” attribute lambda expression pointing to the form field.

Is Blazor good enough? ›

Blazor is a tough sell to current web developer, because it means leaving behind many of the libraries and technologies that have been up over a decade of modern JavaScript development. It's not a seamless transition, and there's no way to migrate a JavaScript application to a Blazor project.

Is anyone using Blazor in production? ›

Yes, Blazor is ready to be used in production, it is a life changer, Blazor is a framework that optimizes development speed, helps considerably reducing code duplication and inconsistencies between front-end and api/backend models, and in turn it helps reducing bugs and development costs, in top of that, since Blazor ...

How do I navigate to another page in Blazor? ›

You can redirect to a page in Blazor using the Navigation Manager's NavigateTo method. In the following code snippet, it will redirect to the home page when this page gets loaded. Similarly, you can call NavigateTo() method from NavigationManager class anywhere to redirect to another page.

How do you add a validation in Blazor? ›

You can define the form in a Blazor app using "EditForm" component. The Blazor engine only validates the input model's property value that is defined in "EditForm" component. The Blazor provides a DataAnnotationsValidator compoment that tells the Blazor engine to validate a model using data annotation.

What is DataAnnotationsValidator? ›

The DataAnnotationsValidator is the standard validator type in Blazor. Adding this component within an EditForm component will enable form validation based on . NET attributes descended from System. ComponentModel. DataAnnotations.

Is Blazor mature enough? ›

Blazor itself is fantastic and mature enough to build on. I've used it (wasm version) on multiple production apps. However, the ecosystem around it isn't quite as developed yet as other front end frameworks. I find myself having to use JSInterop with js libraries some complex web components.

Is angular better than Blazor? ›

Advantages of Angular

Support: The size of the community using Angular is very high when compared to Blazor. So, the chances of finding a solution to the problem we face during the app development are high for Angular. Use of TypeScript: TypeScript has attributes that are way better than JavaScript's.

Is React better than Blazor? ›

Essentially, Blazor allows a developer to build interactive client-side applications with HTML, CSS, and C#. On the other hand, React is a declarative, efficient, and flexible JavaScript library for building user interfaces and UI components.

How many companies use Blazor? ›

Who uses Blazor? 21 companies reportedly use Blazor in their tech stacks, including Scopeland Technology GmbH, Objectivity Software Development, and Weland Solutions AB.

Is Blazor worth learning? ›

The framework enables developers to build interactive and reusable web UI in existing web technologies like C# or HTML. When it comes to grammar and syntax, the framework allows developers to use the ones of Razor and C#. Even though Blazor has accumulated only 9k+ starts on GitHub, it's still worth considering.

Is Microsoft using Blazor? ›

Blazor
Original author(s)Microsoft
Included withASP.NET Core
TypeWeb framework
LicenseApache License 2.0
Websiteblazor.net
5 more rows

How do you pass data between components in Blazor? ›

There are three steps to this solution: Define an event callback in your first component. Define a parameter in your second component. Define a property in your parent component (your page).

How do you refresh a page in Blazor? ›

A page is reloaded/refreshed automatically at a specified interval using “NavigationManager” in OnAfterRender() method. Here the NavigateTo(“url”, forceLoad: true) method, is used to force load the browser based on the URI.

How do I get the current URL in Blazor? ›

Inject NavigationManager in razor. Use Uri from NavigationManager to get the current URL.

How do you manually trigger the form validation in Blazor? ›

You have to define and bind the EditContext with EditForm and then call the method editContext. Validate() on button click to manually trigger the validation.

How check email ID is valid or not in C#? ›

How to Validate an Email Address in C#
  1. Validate email addresses using the MailAddress class.
  2. Validate email addresses with regex. Regular expression for email in C# ...
  3. Validate Email Addresses using Data Annotations. Using EmailAddress attribute. ...
  4. If you're using external libraries. GemBox.Email. ...
  5. What's next?
28 Feb 2022

Do we need validation from others? ›

Validation is part of being interdependent and relying on the feedback and encouragement of others around us. Even very independent people still need validation in some aspects of their life; however, they are also able to accept their own self-validation if they do not get it from someone else.

How do you validate a form in HTML? ›

Mainly there are two ways to perform HTML form validation. The first is using the built-in functionality provided in HTML5, and the second is by using JavaScript. Using the first method, we don't need to write extra code.

Can Blazor replace JavaScript? ›

So Blazor can replace an app made with react/Vue, and instead of writing Javascript /typescript you will be writing C#.

Which is better Blazor server or WebAssembly? ›

Blazor WebAssembly apps can run offline, which is particularly useful when clients aren't able to connect to the Internet. Blazor Server apps fail to run when the connection to the server is lost. If an app must run offline, Blazor WebAssembly is the best choice.

Is Blazor good for enterprise applications? ›

Blazor is highly efficient and has a productive programming model and poses a threat to JavaScript single application (SPA) framework. The way Blazor has been made makes it highly flexible and its runs on the full . NET Core runtime. It also runs on a fast development cycle and has a small download size.”

Why Blazor is the future? ›

Blazor solves one of the big challenges: many web programmers were strong in programming in C#, the most widely used programming language in the Microsoft . Net ecosystem, but they could never really get comfortable with web frontend frameworks, and specifically Javascript.

Is Blazor slower than Angular? ›

It was written under the . NET platform, bringing all the power of Microsoft's framework, both in the client and the server. In this article, we'll compare Angular and Blazor.
...
Comparison table for Blazor and Angular.
AngularBlazor
CI/CD time: 10-20 times slowerCI/CD: 10-20 times faster
9 more rows
24 Feb 2022

Is Blazor fast? ›

In our performance tests, Blazor WebAssembly in . NET 5 is 2-3x faster for most scenarios. "Runtime code execution in Blazor WebAssembly in . NET 5 is generally faster than Blazor WebAssembly 3.2 due to optimizations in the core framework libraries and improvements to the .

Is React faster than Blazor? ›

This does not mean that Blazor is slow, but the download and render time that app developers experience in React will be better. If you take into consideration an app's entire React stack, your React app could experience a slower first-time load.
...
Performance Comparison:
ReactBlazor
LanguageJavaScript/JSX/TypeScriptC#
18 more rows
11 May 2021

Can C# replace JavaScript? ›

C# is replacing the js part using web assembly. So nothing has changed on how you access/modify HTML controls. Also, JS and C# code can interact with Each other. There is a facility to interop, meaning we can call the Javascript code from C# code and vice-versa.

What websites use Blazor? ›

Websites using Blazor
#WebsiteTraffic
1lostmerchants.com3%
2mudblazor.com3%
3textverified.com2%
4myaccount.epsilonnet.gr1%
6 more rows

Is Blazor worth using? ›

The framework enables developers to build interactive and reusable web UI in existing web technologies like C# or HTML. When it comes to grammar and syntax, the framework allows developers to use the ones of Razor and C#. Even though Blazor has accumulated only 9k+ starts on GitHub, it's still worth considering.

Can Blazor replace JavaScript? ›

So Blazor can replace an app made with react/Vue, and instead of writing Javascript /typescript you will be writing C#.

What companies use Blazor? ›

Net now, and also a Blazor server.
...
21 companies reportedly use Blazor in their tech stacks, including Scopeland Technology GmbH, Objectivity Software Development, and Weland Solutions AB.
  • Scopeland Technology ...
  • Objectivity Software ...
  • Weland Solutions ...
  • PokitPal.
  • workspace.
  • Hetosoft Sistemas.
  • Powered4 TV.
  • Pernod Ricard.

Videos

1. Handling Errors Globally in ASP .NET Core Web API
(Study Mash)
2. Blazor Tutorial : Handling Exceptions - EP30
(Curious Drive)
3. ERROR HANDLING In ASP NET Core | Getting Started With ASP.NET Core Series
(Rahul Nath)
4. Best 9 Practices to Follow While Developing Blazor Components for Big Apps | AK Academy
(AK Academy)
5. Blazor App Handling Errors Using Error Boundaries Component[.NET6 Feature]
(Naveen Bommidi Tech Seeker)
6. EFS023: Handling Critical API Errors in Blazor
(Hassan Habib)

Top Articles

Latest Posts

Article information

Author: Sen. Ignacio Ratke

Last Updated: 11/27/2022

Views: 5918

Rating: 4.6 / 5 (56 voted)

Reviews: 95% of readers found this page helpful

Author information

Name: Sen. Ignacio Ratke

Birthday: 1999-05-27

Address: Apt. 171 8116 Bailey Via, Roberthaven, GA 58289

Phone: +2585395768220

Job: Lead Liaison

Hobby: Lockpicking, LARPing, Lego building, Lapidary, Macrame, Book restoration, Bodybuilding

Introduction: My name is Sen. Ignacio Ratke, I am a adventurous, zealous, outstanding, agreeable, precious, excited, gifted person who loves writing and wants to share my knowledge and understanding with you.