I'm trying to understand exception handling in Blazor Server (.net 7)
-
My _Layout.cshtml has a dev with id
blazor-error-ui
. It displays if an unhandled exeption bubbles up in the application. Is Blazor server hardcoded to look for an element with that id, or is the behaviour wired up somewhere in an application? -
If my app raises an exception in an
OnInitializedAsync
,OnInitialized
,OnAfterRender
orOnAfterRender
event, the exception will bubble up and the application will handle it. I'll see the error in theblazor-error-ui
div. Expected behaviour. -
If I have a function which is bound to a property of a component, for example
@bind-Value:after
, and an exception is thrown in that function, the exception does not bubble up and display in theblazor-error-ui
div. -
Further, if I have a component that has an event invoked by
InvokeAsync
, the exception does not bubble up and display in theblazor-error-ui
div. The comppnent invoking the function is the Blazorise Tabs controls SelectedTabChanged event, which I beleive doesn't use an await on the InvokeAsync. The Clicked event of the Tab component uses an await, and those exceptions do display in theblazor-error-ui
div. When shouldInvokeAsync
be called with await vs not? Is that a bug in the component?protected override void OnInitialized() { throw new Exception("This exception will be seen."); }
...
//This function is called by the Tabs component, using InvokeAsync private void SelectedTabChanged() { throw new Exception("This exception will not be seen."); }
<Tabs @bind-SelectedTab="SelectedTab" @bind-SelectedTab:after="AfterSelectedTabChanged"> ...
private async Task AfterSelectedTabChanged(string tab) { throw new Exception("This exception will not be seen."); }
Answwers
In Blazor Server, unhandled exceptions that occur during component lifecycle methods such as OnInitializedAsync
, OnInitialized
, OnAfterRender
, and OnAfterRenderAsync
are automatically captured and displayed in the blazor-error-ui
div in the _Layout.cshtml
file. This behavior is wired up by default in the Blazor Server framework.
However, exceptions thrown in other methods, such as event handlers or methods invoked by event handlers, are not automatically captured and displayed in the blazor-error-ui
div. You need to handle these exceptions explicitly if you want them to be captured and displayed.
Regarding your observations:
-
Exceptions thrown in methods bound to properties (e.g.,
@bind-Value:after
) or invoked by components usingInvokeAsync
are not automatically captured and displayed in theblazor-error-ui
div. You need to handle these exceptions manually by implementing error handling logic in those methods. -
When using
InvokeAsync
, you typically useawait
if you want to wait for the invoked task to complete before proceeding with subsequent code execution. If you don't useawait
, the method will continue executing without waiting for the invoked task to complete. Whether to useawait
or not depends on your specific use case and whether you need to wait for the task to complete before proceeding. -
The behavior you described with the Blazorise Tabs control's
SelectedTabChanged
event not displaying exceptions in theblazor-error-ui
div may be due to how the event is implemented in the Blazorise library. If the event handler internally catches exceptions and does not propagate them, they won't be captured by the framework's error handling mechanism. You may need to check the documentation or source code of the Blazorise Tabs control to understand its error handling behavior and determine if it's a bug or expected behavior.
In summary, exceptions thrown in component lifecycle methods are automatically captured and displayed in the blazor-error-ui
div, but exceptions thrown in other methods or event handlers need to be handled manually if you want them to be captured and displayed. Additionally, whether to use await
with InvokeAsync
depends on your specific use case and requirements.