如何在Blazor WASM(ASP.NET Core托管)模板中正确显示错误页?
在Blazor托管模板中正常显示服务端错误页的方案
问题根源
Blazor WASM客户端是单页应用,服务端通过app.UseExceptionHandler("/Error");返回的HTML错误页会被客户端路由系统忽略,无法被正常渲染,只能在浏览器检查器中看到原始响应内容。
两种可行解决方案
方案一:服务端返回结构化错误,客户端处理显示
适合API请求场景,让服务端返回JSON格式的错误信息,客户端捕获后显示自定义错误UI:
- 修改服务端异常处理逻辑
替换原有的app.UseExceptionHandler("/Error");,改为返回JSON错误:app.UseExceptionHandler(errorApp => { errorApp.Run(async context => { context.Response.StatusCode = StatusCodes.Status500InternalServerError; context.Response.ContentType = "application/json"; var exceptionFeature = context.Features.Get<IExceptionHandlerPathFeature>(); var errorDetails = new { Message = "服务器运行时发生异常", ExceptionMessage = exceptionFeature?.Error.Message, RequestPath = exceptionFeature?.Path }; await context.Response.WriteAsJsonAsync(errorDetails); }); }); - 客户端全局错误处理
- 在
App.razor中用ErrorBoundary组件包裹路由区域,统一处理组件级错误:<ErrorBoundary> <Router AppAssembly="@typeof(App).Assembly"> <Found Context="routeData"> <RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" /> </Found> <NotFound> <LayoutView Layout="@typeof(MainLayout)"> <p>请求的页面不存在</p> </LayoutView> </NotFound> </Router> <ChildContent> <LayoutView Layout="@typeof(MainLayout)"> <h2>抱歉,发生了未知错误</h2> <p>@context?.Exception.Message</p> </LayoutView> </ChildContent> </ErrorBoundary> - 对于API调用,在客户端的HTTP服务中捕获异常,显示对应提示:
public async Task<T> GetAsync<T>(string url) { try { var response = await _httpClient.GetFromJsonAsync<T>(url); return response; } catch (HttpRequestException ex) { // 可在此处弹出错误提示或触发全局错误状态 Console.WriteLine($"API请求错误: {ex.Message}"); throw; } }
- 在
方案二:复用服务端错误页内容,在客户端渲染
如果需要保留原Razor错误页的内容,可以将错误页改为共享组件,让客户端和服务端都能使用:
- 将服务端Error页转为共享组件
在Shared项目中创建ErrorComponent.razor,迁移原服务端Error.cshtml的内容:<h1>服务器错误</h1> <p>请求处理时出现问题,请稍后重试。</p> @if (ErrorDetails != null) { <p>错误详情: @ErrorDetails.Message</p> } @code { [Parameter] public object ErrorDetails { get; set; } } - 调整服务端异常处理逻辑
判断请求是否来自Blazor客户端,重定向到客户端的错误路由:app.UseExceptionHandler(errorApp => { errorApp.Run(async context => { // 通过请求头判断是否为Blazor客户端请求 var isBlazorClient = context.Request.Headers["Accept"].ToString().Contains("text/html") && !context.Request.Path.StartsWithSegments("/api"); if (isBlazorClient) { // 重定向到客户端错误路由 context.Response.Redirect("/client-error"); } else { // 非Blazor请求返回原HTML错误页 var exceptionFeature = context.Features.Get<IExceptionHandlerPathFeature>(); await context.Response.WriteAsync($"<html><body><h1>服务器错误</h1><p>{exceptionFeature?.Error.Message}</p></body></html>"); } }); }); - 客户端添加错误路由
在App.razor的Router中添加全局错误捕获:
同时在客户端<Router AppAssembly="@typeof(App).Assembly"> <Found Context="routeData"> <RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" /> </Found> <NotFound> <LayoutView Layout="@typeof(MainLayout)"> <p>请求的页面不存在</p> </LayoutView> </NotFound> <!-- 全局错误捕获 --> <Error> <LayoutView Layout="@typeof(MainLayout)"> <Shared.ErrorComponent ErrorDetails="@context.Exception" /> </LayoutView> </Error> </Router>Routes.razor中添加/client-error路由:<Route Route="/client-error"> <Shared.ErrorComponent /> </Route>
注意事项
- 区分API请求和页面请求:API请求优先返回JSON错误,页面请求可返回客户端可渲染的错误组件
- 如果使用预渲染模式,服务端的错误可直接在预渲染阶段显示,无需额外处理
内容的提问来源于stack exchange,提问作者cjadd7
相关产品推荐
相关产品推荐

