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

如何在Blazor Server中全局捕获并记录控制器异常?

Blazor WASM Core托管应用全局异常捕获方案

后端(ASP.NET Core)全局异常处理中间件

无需在每个控制器方法中添加try-catch,通过全局中间件即可捕获所有请求的未处理异常,并提取控制器、代码行等详细信息:

  1. 创建异常处理中间件类
public class GlobalExceptionMiddleware
{
    private readonly RequestDelegate _next;
    private readonly ILogger<GlobalExceptionMiddleware> _logger;
    private readonly IWebHostEnvironment _env;

    public GlobalExceptionMiddleware(RequestDelegate next, ILogger<GlobalExceptionMiddleware> logger, IWebHostEnvironment env)
    {
        _next = next;
        _logger = logger;
        _env = env;
    }

    public async Task InvokeAsync(HttpContext context)
    {
        try
        {
            await _next(context);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "未处理异常触发");
            await HandleExceptionAsync(context, ex);
        }
    }

    private async Task HandleExceptionAsync(HttpContext context, Exception ex)
    {
        context.Response.ContentType = "application/json";
        context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;

        var errorResponse = new
        {
            StatusCode = context.Response.StatusCode,
            Message = _env.IsDevelopment() ? ex.Message : "服务器内部错误",
            DetailedInfo = _env.IsDevelopment() ? ex.ToString() : null,
            ControllerName = context.GetRouteValue("controller")?.ToString(),
            ActionName = context.GetRouteValue("action")?.ToString()
        };

        await context.Response.WriteAsJsonAsync(errorResponse);
    }
}
  1. 在Program.cs中注册中间件
    注意中间件顺序,需放在UseRouting之后、UseAuthorization之前:
var builder = WebApplication.CreateBuilder(args);

// 注册其他服务...

var app = builder.Build();

// 配置其他中间件...

app.UseMiddleware<GlobalExceptionMiddleware>();

app.UseRouting();
app.UseAuthorization();

app.MapControllers();
app.MapBlazorHub();
app.MapFallbackToPage("/_Host");

app.Run();

前端(Blazor WASM)接收并处理后端异常

前端调用API时,统一处理后端返回的自定义错误信息,再传递给ErrorBoundary处理:

  1. 封装HttpClient统一处理错误
public class ApiService
{
    private readonly HttpClient _httpClient;

    public ApiService(HttpClient httpClient)
    {
        _httpClient = httpClient;
    }

    public async Task<T> GetAsync<T>(string url)
    {
        var response = await _httpClient.GetAsync(url);
        if (!response.IsSuccessStatusCode)
        {
            var error = await response.Content.ReadFromJsonAsync<ErrorResponse>();
            throw new Exception(error?.DetailedInfo ?? error?.Message ?? "请求失败");
        }
        return await response.Content.ReadFromJsonAsync<T>();
    }

    // 同理封装PostAsync、PutAsync等方法
}

public class ErrorResponse
{
    public int StatusCode { get; set; }
    public string Message { get; set; }
    public string DetailedInfo { get; set; }
    public string ControllerName { get; set; }
    public string ActionName { get; set; }
}
  1. 在ErrorBoundary中展示详细异常信息
    修改ErrorBoundary的错误内容模板,展示后端返回的完整异常信息:
<ErrorBoundary>
    <ChildContent>
        @Body
    </ChildContent>
    <ErrorContent Context="exception">
        <div class="alert alert-danger">
            <h3>错误提示</h3>
            <p>@exception.Message</p>
            @if (!string.IsNullOrEmpty(exception.ToString()))
            {
                <details>
                    <summary>查看详细信息</summary>
                    <pre>@exception.ToString()</pre>
                </details>
            }
            @SaveLogs(exception)
        </div>
    </ErrorContent>
</ErrorBoundary>

核心说明

  • 开发环境返回完整异常栈、控制器及代码行信息,生产环境自动隐藏敏感细节,避免代码泄露
  • 中间件覆盖所有控制器请求的未处理异常,无需在单个Action中编写try-catch
  • 前端通过封装HttpClient,将后端错误信息包装为Exception,让ErrorBoundary可以直接捕获并处理

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 18:31:02