Skip to content

Commit 4639b06

Browse files
authored
Error handling section improvements (#33106)
1 parent 200f964 commit 4639b06

File tree

1 file changed

+52
-48
lines changed

1 file changed

+52
-48
lines changed

aspnetcore/blazor/fundamentals/handle-errors.md

Lines changed: 52 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -206,10 +206,10 @@ The framework terminates a circuit when an unhandled exception occurs for the fo
206206

207207
:::moniker range=">= aspnetcore-6.0"
208208

209-
For global exception handling, see the following sections:
209+
For approaches to handling exceptions globally, see the following sections:
210210

211-
* [Error boundaries](#error-boundaries)
212-
* [Alternative global exception handling](#alternative-global-exception-handling)
211+
* [Error boundaries](#error-boundaries): Applies to all Blazor apps.
212+
* [Alternative global exception handling](#alternative-global-exception-handling): Applies to Blazor Server, Blazor WebAssembly, and Blazor Web Apps (8.0 or later) that adopt a global interactive render mode.
213213

214214
## Error boundaries
215215

@@ -331,14 +331,24 @@ To avoid the infinite loop where recovering merely rerenders a component that th
331331

332332
## Alternative global exception handling
333333

334+
:::moniker-end
335+
336+
:::moniker range=">= aspnetcore-8.0"
337+
338+
The approach described in this section applies to Blazor Server, Blazor WebAssembly, and Blazor Web Apps that adopt a global interactive render mode (`InteractiveServer`, `InteractiveWebAssembly`, or `InteractiveAuto`). The approach doesn't work with Blazor Web Apps that adopt per-page/component render modes or static server-side rendering (static SSR) because the approach relies on a [`CascadingValue`](xref:blazor/components/cascading-values-and-parameters#cascadingvalue-component)/[`CascadingParameter`](xref:blazor/components/cascading-values-and-parameters#cascadingparameter-attribute), which don't work across render mode boundaries or with components that adopt static SSR.
339+
340+
:::moniker-end
341+
342+
:::moniker range=">= aspnetcore-6.0"
343+
334344
An alternative to using [Error boundaries](#error-boundaries) (<xref:Microsoft.AspNetCore.Components.Web.ErrorBoundary>) is to pass a custom error component as a [`CascadingValue`](xref:blazor/components/cascading-values-and-parameters#cascadingvalue-component) to child components. An advantage of using a component over using an [injected service](xref:blazor/fundamentals/dependency-injection) or a custom logger implementation is that a cascaded component can render content and apply CSS styles when an error occurs.
335345

336-
The following `Error` component example merely logs errors, but methods of the component can process errors in any way required by the app, including through the use of multiple error processing methods.
346+
The following `ProcessError` component example merely logs errors, but methods of the component can process errors in any way required by the app, including through the use of multiple error processing methods.
337347

338-
`Error.razor`:
348+
`ProcessError.razor`:
339349

340350
```razor
341-
@inject ILogger<Error> Logger
351+
@inject ILogger<ProcessError> Logger
342352
343353
<CascadingValue Value="this">
344354
@ChildContent
@@ -348,13 +358,13 @@ The following `Error` component example merely logs errors, but methods of the c
348358
[Parameter]
349359
public RenderFragment? ChildContent { get; set; }
350360
351-
public void ProcessError(Exception ex)
361+
public void LogError(Exception ex)
352362
{
353-
Logger.LogError("Error:ProcessError - Type: {Type} Message: {Message}",
363+
Logger.LogError("ProcessError.LogError: {Type} Message: {Message}",
354364
ex.GetType(), ex.Message);
355365
356-
// Call StateHasChanged if ProcessError directly participates in
357-
// rendering. If ProcessError only logs or records the error,
366+
// Call StateHasChanged if LogError directly participates in
367+
// rendering. If LogError only logs or records the error,
358368
// there's no need to call StateHasChanged.
359369
//StateHasChanged();
360370
}
@@ -368,55 +378,51 @@ The following `Error` component example merely logs errors, but methods of the c
368378

369379
:::moniker range=">= aspnetcore-8.0"
370380

371-
In the `Routes` component, wrap the <xref:Microsoft.AspNetCore.Components.Routing.Router> component (`<Router>...</Router>`) with the `Error` component. This permits the `Error` component to cascade down to any component of the app where the `Error` component is received as a [`CascadingParameter`](xref:blazor/components/cascading-values-and-parameters#cascadingparameter-attribute).
381+
When using this approach in a Blazor Web App, open the `Routes` component and wrap the <xref:Microsoft.AspNetCore.Components.Routing.Router> component (`<Router>...</Router>`) with the `ProcessError` component. This permits the `ProcessError` component to cascade down to any component of the app where the `ProcessError` component is received as a [`CascadingParameter`](xref:blazor/components/cascading-values-and-parameters#cascadingparameter-attribute).
372382

373383
In `Routes.razor`:
374384

375385
```razor
376-
<Error>
386+
<ProcessError>
377387
<Router ...>
378388
...
379389
</Router>
380-
</Error>
390+
</ProcessError>
381391
```
382392

383393
:::moniker-end
384394

385-
:::moniker range=">= aspnetcore-6.0 < aspnetcore-8.0"
395+
:::moniker range=">= aspnetcore-6.0"
386396

387-
In the `App` component, wrap the <xref:Microsoft.AspNetCore.Components.Routing.Router> component (`<Router>...</Router>`) with the `Error` component. This permits the `Error` component to cascade down to any component of the app where the `Error` component is received as a [`CascadingParameter`](xref:blazor/components/cascading-values-and-parameters#cascadingparameter-attribute).
397+
When using this approach in a Blazor Server or Blazor WebAssembly app, open the `App` component, wrap the <xref:Microsoft.AspNetCore.Components.Routing.Router> component (`<Router>...</Router>`) with the `ProcessError` component. This permits the `ProcessError` component to cascade down to any component of the app where the `ProcessError` component is received as a [`CascadingParameter`](xref:blazor/components/cascading-values-and-parameters#cascadingparameter-attribute).
388398

389399
In `App.razor`:
390400

391401
```razor
392-
<Error>
402+
<ProcessError>
393403
<Router ...>
394404
...
395405
</Router>
396-
</Error>
406+
</ProcessError>
397407
```
398408

399-
:::moniker-end
400-
401-
:::moniker range=">= aspnetcore-6.0"
402-
403409
To process errors in a component:
404410

405-
* Designate the `Error` component as a [`CascadingParameter`](xref:blazor/components/cascading-values-and-parameters#cascadingparameter-attribute) in the [`@code`](xref:mvc/views/razor#code) block. In an example `Counter` component in an app based on a Blazor project template, add the following `Error` property:
411+
* Designate the `ProcessError` component as a [`CascadingParameter`](xref:blazor/components/cascading-values-and-parameters#cascadingparameter-attribute) in the [`@code`](xref:mvc/views/razor#code) block. In an example `Counter` component in an app based on a Blazor project template, add the following `ProcessError` property:
406412

407413
```csharp
408414
[CascadingParameter]
409-
public Error? Error { get; set; }
415+
public ProcessError? ProcessError { get; set; }
410416
```
411417

412-
* Call an error processing method in any `catch` block with an appropriate exception type. The example `Error` component only offers a single `ProcessError` method, but the error processing component can provide any number of error processing methods to address alternative error processing requirements throughout the app. In the following `Counter` component example, an exception is thrown and trapped when the count is greater than five:
418+
* Call an error processing method in any `catch` block with an appropriate exception type. The example `ProcessError` component only offers a single `LogError` method, but the error processing component can provide any number of error processing methods to address alternative error processing requirements throughout the app. The following `Counter` component `@code` block example includes the `ProcessError` cascading parameter and traps an exception for logging when the count is greater than five:
413419

414420
```razor
415421
@code {
416422
private int currentCount = 0;
417423
418424
[CascadingParameter]
419-
public Error? Error { get; set; }
425+
public ProcessError? ProcessError { get; set; }
420426
421427
private void IncrementCount()
422428
{
@@ -431,20 +437,18 @@ To process errors in a component:
431437
}
432438
catch (Exception ex)
433439
{
434-
Error?.ProcessError(ex);
440+
ProcessError?.LogError(ex);
435441
}
436442
}
437443
}
438444
```
439445

440-
Using the preceding `Error` component with the preceding changes made to a `Counter` component, the browser's developer tools console indicates the trapped, logged error:
446+
The logged error:
441447

442-
```console
443-
fail: {COMPONENT NAMESPACE}.Error[0]
444-
Error:ProcessError - Type: System.InvalidOperationException Message: Current count is over five!
445-
```
448+
> :::no-loc text="fail: {COMPONENT NAMESPACE}.ProcessError[0]":::
449+
> :::no-loc text="ProcessError.LogError: System.InvalidOperationException Message: Current count is over five!":::
446450
447-
If the `ProcessError` method directly participates in rendering, such as showing a custom error message bar or changing the CSS styles of the rendered elements, call [`StateHasChanged`](xref:blazor/components/lifecycle#state-changes-statehaschanged) at the end of the `ProcessErrors` method to rerender the UI.
451+
If the `LogError` method directly participates in rendering, such as showing a custom error message bar or changing the CSS styles of the rendered elements, call [`StateHasChanged`](xref:blazor/components/lifecycle#state-changes-statehaschanged) at the end of the `LogError` method to rerender the UI.
448452

449453
Because the approaches in this section handle errors with a [`try-catch`](/dotnet/csharp/language-reference/keywords/try-catch) statement, an app's SignalR connection between the client and server isn't broken when an error occurs and the circuit remains alive. Other unhandled exceptions remain fatal to a circuit. For more information, see the section on [how a circuit reacts to unhandled exceptions](#unhandled-exceptions-for-circuits).
450454

@@ -454,13 +458,13 @@ Because the approaches in this section handle errors with a [`try-catch`](/dotne
454458

455459
An app can use an error processing component as a cascading value to process errors in a centralized way.
456460

457-
The following `Error` component passes itself as a [`CascadingValue`](xref:blazor/components/cascading-values-and-parameters#cascadingvalue-component) to child components. The following example merely logs the error, but methods of the component can process errors in any way required by the app, including through the use of multiple error processing methods. An advantage of using a component over using an [injected service](xref:blazor/fundamentals/dependency-injection) or a custom logger implementation is that a cascaded component can render content and apply CSS styles when an error occurs.
461+
The following `ProcessError` component passes itself as a [`CascadingValue`](xref:blazor/components/cascading-values-and-parameters#cascadingvalue-component) to child components. The following example merely logs the error, but methods of the component can process errors in any way required by the app, including through the use of multiple error processing methods. An advantage of using a component over using an [injected service](xref:blazor/fundamentals/dependency-injection) or a custom logger implementation is that a cascaded component can render content and apply CSS styles when an error occurs.
458462

459-
`Error.razor`:
463+
`ProcessError.razor`:
460464

461465
```razor
462466
@using Microsoft.Extensions.Logging
463-
@inject ILogger<Error> Logger
467+
@inject ILogger<ProcessError> Logger
464468
465469
<CascadingValue Value="this">
466470
@ChildContent
@@ -470,9 +474,9 @@ The following `Error` component passes itself as a [`CascadingValue`](xref:blazo
470474
[Parameter]
471475
public RenderFragment ChildContent { get; set; }
472476
473-
public void ProcessError(Exception ex)
477+
public void LogError(Exception ex)
474478
{
475-
Logger.LogError("Error:ProcessError - Type: {Type} Message: {Message}",
479+
Logger.LogError("ProcessError.LogError: {Type} Message: {Message}",
476480
ex.GetType(), ex.Message);
477481
}
478482
}
@@ -481,28 +485,28 @@ The following `Error` component passes itself as a [`CascadingValue`](xref:blazo
481485
> [!NOTE]
482486
> For more information on <xref:Microsoft.AspNetCore.Components.RenderFragment>, see <xref:blazor/components/index#child-content-render-fragments>.
483487
484-
In the `App` component, wrap the <xref:Microsoft.AspNetCore.Components.Routing.Router> component with the `Error` component. This permits the `Error` component to cascade down to any component of the app where the `Error` component is received as a [`CascadingParameter`](xref:blazor/components/cascading-values-and-parameters#cascadingparameter-attribute).
488+
In the `App` component, wrap the <xref:Microsoft.AspNetCore.Components.Routing.Router> component with the `ProcessError` component. This permits the `ProcessError` component to cascade down to any component of the app where the `ProcessError` component is received as a [`CascadingParameter`](xref:blazor/components/cascading-values-and-parameters#cascadingparameter-attribute).
485489

486490
`App.razor`:
487491

488492
```razor
489-
<Error>
493+
<ProcessError>
490494
<Router ...>
491495
...
492496
</Router>
493-
</Error>
497+
</ProcessError>
494498
```
495499

496500
To process errors in a component:
497501

498-
* Designate the `Error` component as a [`CascadingParameter`](xref:blazor/components/cascading-values-and-parameters#cascadingparameter-attribute) in the [`@code`](xref:mvc/views/razor#code) block:
502+
* Designate the `ProcessError` component as a [`CascadingParameter`](xref:blazor/components/cascading-values-and-parameters#cascadingparameter-attribute) in the [`@code`](xref:mvc/views/razor#code) block:
499503

500504
```razor
501505
[CascadingParameter]
502-
public Error Error { get; set; }
506+
public ProcessError ProcessError { get; set; }
503507
```
504508

505-
* Call an error processing method in any `catch` block with an appropriate exception type. The example `Error` component only offers a single `ProcessError` method, but the error processing component can provide any number of error processing methods to address alternative error processing requirements throughout the app.
509+
* Call an error processing method in any `catch` block with an appropriate exception type. The example `ProcessError` component only offers a single `LogError` method, but the error processing component can provide any number of error processing methods to address alternative error processing requirements throughout the app.
506510

507511
```csharp
508512
try
@@ -511,16 +515,16 @@ To process errors in a component:
511515
}
512516
catch (Exception ex)
513517
{
514-
Error.ProcessError(ex);
518+
ProcessError.LogError(ex);
515519
}
516520
```
517521

518-
Using the preceding example `Error` component and `ProcessError` method, the browser's developer tools console indicates the trapped, logged error:
522+
Using the preceding example `ProcessError` component and `LogError` method, the browser's developer tools console indicates the trapped, logged error:
519523

520-
> fail: BlazorSample.Shared.Error[0]
521-
> Error:ProcessError - Type: System.NullReferenceException Message: Object reference not set to an instance of an object.
524+
> :::no-loc text="fail: {COMPONENT NAMESPACE}.Shared.ProcessError[0]":::
525+
> :::no-loc text="ProcessError.LogError: System.NullReferenceException Message: Object reference not set to an instance of an object.":::
522526
523-
If the `ProcessError` method directly participates in rendering, such as showing a custom error message bar or changing the CSS styles of the rendered elements, call [`StateHasChanged`](xref:blazor/components/lifecycle#state-changes-statehaschanged) at the end of the `ProcessErrors` method to rerender the UI.
527+
If the `LogError` method directly participates in rendering, such as showing a custom error message bar or changing the CSS styles of the rendered elements, call [`StateHasChanged`](xref:blazor/components/lifecycle#state-changes-statehaschanged) at the end of the `LogError` method to rerender the UI.
524528

525529
Because the approaches in this section handle errors with a [`try-catch`](/dotnet/csharp/language-reference/keywords/try-catch) statement, a Blazor app's SignalR connection between the client and server isn't broken when an error occurs and the circuit remains alive. Any unhandled exception is fatal to a circuit. For more information, see the section on [how a circuit reacts to unhandled exceptions](#unhandled-exceptions-for-circuits).
526530

0 commit comments

Comments
 (0)