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

Blazor WebAssembly全局捕获Razor组件异常并输出至浏览器控制台方案

Blazor WebAssembly 全局异常捕获方案

部署位置与Program.cs的可行性

完全可以把全局异常捕获逻辑放在Program.cs中,这是最推荐的位置——因为Program.cs是Blazor WebAssembly应用的启动入口,在这里配置的逻辑会全局生效,无需在多个文件中重复设置。

全局捕获实现方案

以下是一套完整的全局异常捕获配置,覆盖组件异常、异步任务异常、AppDomain级未捕获异常三类场景,所有逻辑集中在Program.cs中,配合App.razor的ErrorBoundary实现全链路捕获:

1. Program.cs 核心配置

var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
builder.RootComponents.Add<HeadOutlet>("head::after");

// 注册全局组件异常日志服务
builder.Services.AddSingleton<IErrorBoundaryLogger, GlobalErrorLogger>();

// 捕获未被观察到的异步任务异常
TaskScheduler.UnobservedTaskException += (sender, e) =>
{
    LogExceptionDetails(e.Exception, "未捕获异步任务异常");
    e.SetObserved(); // 标记异常已处理,避免应用崩溃
};

// 捕获AppDomain级别的未捕获异常
AppDomain.CurrentDomain.UnhandledException += (sender, e) =>
{
    if (e.ExceptionObject is Exception ex)
    {
        LogExceptionDetails(ex, "AppDomain未捕获异常");
    }
};

var host = builder.Build();
await host.RunAsync();

// 统一异常日志输出方法
void LogExceptionDetails(Exception ex, string exceptionContext)
{
    Console.WriteLine($"===== {exceptionContext} =====");
    Console.WriteLine($"异常类型: {ex.GetType().FullName}");
    Console.WriteLine($"异常消息: {ex.Message}");
    Console.WriteLine($"异常位置:\n{ex.StackTrace}");
    
    if (ex.InnerException != null)
    {
        Console.WriteLine("\n===== 内部异常 =====");
        Console.WriteLine($"异常类型: {ex.InnerException.GetType().FullName}");
        Console.WriteLine($"异常消息: {ex.InnerException.Message}");
        Console.WriteLine($"异常位置:\n{ex.InnerException.StackTrace}");
    }
}

// 自定义ErrorBoundary日志实现类
public class GlobalErrorLogger : IErrorBoundaryLogger
{
    public ValueTask LogErrorAsync(Exception exception, ComponentErrorBoundary boundary)
    {
        LogExceptionDetails(exception, $"组件异常 (组件边界: {boundary.GetType().Name})");
        return ValueTask.CompletedTask;
    }
}

2. App.razor 配套配置

在App.razor中用ErrorBoundary包裹整个路由组件,确保所有页面组件的异常都能被捕获:

<ErrorBoundary>
    <ChildContent>
        <Router AppAssembly="@typeof(App).Assembly">
            <Found Context="routeData">
                <RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
                <FocusOnNavigate RouteData="@routeData" Selector="h1" />
            </Found>
            <NotFound>
                <PageTitle>Not found</PageTitle>
                <LayoutView Layout="@typeof(MainLayout)">
                    <p role="alert">Sorry, there's nothing at this address.</p>
                </LayoutView>
            </NotFound>
        </Router>
    </ChildContent>
</ErrorBoundary>

关键说明

  • 该方案实现一处配置全局生效:所有组件的同步/异步异常、未被等待的异步任务异常、顶级未捕获异常都会被捕获并输出到浏览器控制台。
  • 日志内容包含异常类型、消息、堆栈跟踪(明确异常位置),以及内部异常信息,满足调试需求。
  • 如果需要扩展(比如将异常上报到后端),只需修改LogExceptionDetails方法即可,无需改动其他代码。

内容的提问来源于stack exchange,提问作者userxchange123

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 21:12:36