.NET MAUI Blazor如何捕获错误并显示在页面,ErrorBoundary是否兼容?
MAUI Blazor ErrorBoundary兼容问题及解决方案
兼容性说明
ErrorBoundary本身是兼容.NET MAUI Blazor的,你遇到的启动崩溃不是组件不支持,而是.NET MAUI Blazor默认的异常处理策略导致:Blazor层抛出的未处理异常会直接传递到MAUI原生运行时,触发应用强制终止,而不会像Blazor WASM那样停留在Blazor上下文交给ErrorBoundary处理。
修复步骤
1. 版本适配
如果使用的是.NET 6版本的MAUI,建议升级到.NET 7及以上版本,.NET 6的MAUI Blazor对ErrorBoundary存在已知的适配缺陷,更高版本的运行时已经修复了相关问题。
2. 配置BlazorWebView异常策略
在MauiProgram.cs中配置BlazorWebView的异常处理逻辑,阻止异常抛到原生层:
builder.Services.AddBlazorWebView() .AddComponents(options => { // 阻止未处理异常抛到原生层导致应用崩溃 options.DispatcherOptions.UnhandledException = (sender, e) => { e.SetHandled(); }; });
注:如果仍使用.NET 6版本MAUI,可在MainPage.xaml.cs中订阅BlazorWebView的BlazorWebViewInitializing事件,设置对应异常处理逻辑即可。
3. 全局异常捕获(可选,覆盖非渲染上下文异常)
如果需要捕获Blazor渲染上下文之外的异常(比如后台任务、原生交互抛出的异常),可以添加全局异常状态服务统一收集:
3.1 定义全局异常状态类
public class GlobalExceptionState { public event Action<Exception> OnExceptionOccurred; public void NotifyException(Exception ex) { OnExceptionOccurred?.Invoke(ex); } }
3.2 注册全局异常捕获和服务
在MauiProgram.cs的开头添加如下代码:
var globalExceptionState = new GlobalExceptionState(); // 捕获同步代码未处理异常 AppDomain.CurrentDomain.UnhandledException += (sender, e) => { if (e.ExceptionObject is Exception ex) { globalExceptionState.NotifyException(ex); } e.Handled = true; }; // 捕获异步任务未观察异常 TaskScheduler.UnobservedTaskException += (sender, e) => { globalExceptionState.NotifyException(e.Exception); e.SetObserved(); }; // 注册为单例服务 builder.Services.AddSingleton(globalExceptionState);
3.3 改造CustomErrorBoundary支持全局异常收集
修改你现有的CustomErrorBoundary.razor代码,注入全局异常服务订阅异常:
@inherits ErrorBoundary @inject GlobalExceptionState ExceptionState @implements IDisposable @if (CurrentException is null) { @ChildContent } else if (ErrorContent is not null) { @ErrorContent(CurrentException) } else { <div style="background-color: yellow; border: 2px dashed black; white-space: pre; font-family: consolas, monospace;"> @foreach (var exception in receivedExceptions) { <div class="received-exception" style="background-color: rgba(255,255,255,0.3); margin: 0.5rem; padding: 0.5rem;"> @exception.Message <br> <small style="font-size: 0.8rem;">@exception.StackTrace</small> </div> } <button @onclick="Recover" style="margin: 0.5rem; padding: 0.3rem 0.8rem;">清除错误</button> </div> } @code { List<Exception> receivedExceptions = new(); private Action<Exception> _exceptionSubscription; protected override void OnInitialized() { _exceptionSubscription = ex => { InvokeAsync(() => { receivedExceptions.Add(ex); StateHasChanged(); }); }; ExceptionState.OnExceptionOccurred += _exceptionSubscription; base.OnInitialized(); } protected override Task OnErrorAsync(Exception exception) { receivedExceptions.Add(exception); return base.OnErrorAsync(exception); } public new void Recover() { receivedExceptions.Clear(); base.Recover(); } public void Dispose() { if (_exceptionSubscription != null) { ExceptionState.OnExceptionOccurred -= _exceptionSubscription; } } }
验证
按上述配置完成后,你在WeatherForecastService中抛出的异常就会被ErrorBoundary捕获并展示在页面上,不会再触发应用崩溃。
内容的提问来源于stack exchange,提问作者Bronzato
相关产品推荐
相关产品推荐

