Blazor wasm 原生模版中没有提供对End user友好的异常处理机制. 一般情况下我们都需要自行实现一套自己的异常处理机制
==============================
原生的异常处理机制
==============================
Fetch.razor 的初始化代码, 加载一个不存在的json 文件, 导致程序异常, 未做特殊处理的情况.
protected override async Task OnInitializedAsync()
{
forecasts = await Http.GetFromJsonAsync<WeatherForecast[]>("sample-data/not_found.json");
}
==============================
简单的JS alert处理机制
==============================
注入 IJSRuntime 调用 js alert 函数来处理异常, 对于End user 稍微好了一些, 但还是不够友好.
[Inject] IJSRuntime Js { get; set; }
protected override async Task OnInitializedAsync()
{
try
{
forecasts = await Http.GetFromJsonAsync<WeatherForecast[]>("sample-data/not_found.json");
}
catch (Exception ex)
{
await Js.InvokeVoidAsync("alert", ex.Message);
}
}
==============================
自定义全局异常处理机制: Layout中内置一个全局的ErrorComponent
==============================
1. 声明一个 IErrorComponent 接口
namespace WebApplication2
{
public interface IErrorComponent
{
void ShowError(string title, string message);
}
}
2. MainLayout.razor 实现 IErrorComponent接口, 并提供显示和关闭Error
@inherits LayoutComponentBase
@implements IErrorComponent
<div class="page">
<div class="sidebar">
<NavMenu />
</div>
<div class="main">
<div class="top-row px-4">
<a href="http://blazor.net" target="_blank" class="ml-md-auto">About</a>
</div>
<div class="content px-4">
@if (_IsErrorActive)
{
<div class="alert alert-danger" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close1" @onclick="HideError">
<span aria-hidden="true">×</span>
</button>
</div>
<h3>@_Title</h3>
<p>@_Message</p>
}
<CascadingValue Value="this" Name="ErrorComponent">
@Body
</CascadingValue>
</div>
</div>
</div>
@code{
bool _IsErrorActive;
String _Title;
String _Message;
public void ShowError(string title, string message)
{
this._IsErrorActive = true;
this._Title = title;
this._Message = message;
StateHasChanged();
}
private void HideError()
{
this._IsErrorActive = false;
}
}
改造之前, content 部分非常简单, 代码见下, 改造之后, 在@Body 加了显示 error message的 alert 卡片.
<div class="content px-4">
@Body
</div>
另外, 使用 CascadingValue 组件将 MainLayout 作为 IErrorComponent 的实例传导到各个页面中.
3. FetchData.razor 文件中, 使用 CascadingParameter 承接 IErrorComponent 实例, 并在异常点使用该实例显示出来.
[CascadingParameter(Name = "ErrorComponent")] IErrorComponent _ErrorComponent { get; set; }
protected override async Task OnInitializedAsync()
{
try
{
forecasts = await Http.GetFromJsonAsync<WeatherForecast[]>("sample-data/not_found.json");
}
catch (Exception ex)
{
_ErrorComponent.ShowError(ex.Message, ex.StackTrace);
}
}
效果图:
==============================
参考
==============================
https://nightbaker.github.io/gitflow/azure/piplines/2020/01/22/blazor-error-component/
https://nightbaker.github.io/blazor/exception/2021/08/11/throws-exceptions-to-blazor/