You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 08:36:04