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

ASP.NET Core发生错误时如何记录请求URL 现有中间件仅无错时执行怎么办

问题解答

问题1:当前编写的中间件仅无错误时执行的原因

  • 代码执行顺序错误。你将响应状态码判断、日志记录逻辑全部写在了await next.Invoke()之前,此时后续的业务处理、路由匹配、接口逻辑都还未执行,context.Response.StatusCode还处于初始默认值200,你的错误状态码判断条件自然不会触发。如果后续中间件抛出未处理异常,执行流会直接从await next.Invoke()处向上抛出,你写在调用前的逻辑早已执行完毕,自然捕获不到异常场景。
  • 中间件注册顺序错误。ASP.NET Core中间件遵循「先进后出」的执行顺序,如果你的这个中间件注册在了全局异常处理中间件(如UseExceptionHandler、UseDeveloperExceptionPage)的后方,那么未处理异常会先被前方的异常处理中间件捕获并消化,不会流到你自定义的中间件中。

问题2:未处理异常时记录请求URL与Body的实现方法

方案1:修改自定义中间件实现(兼容性最好)

调整中间件的逻辑顺序,用try-catch包裹await next.Invoke()捕获未处理异常,同时开启请求体缓冲支持重复读取即可:

// 注册中间件时注意要放到所有业务中间件的最前面,排在异常处理中间件之前
app.Use(async (context, next) =>
{
    // 开启请求体缓冲,支持重复读取
    context.Request.EnableBuffering();
    try
    {
        // 先调用后续中间件处理业务
        await next.Invoke();
        // 后续中间件执行完成后判断状态码(处理非异常类的错误,比如404、403等)
        if (context.Response.StatusCode is < 200 or > 299)
        {
            Console.WriteLine($"请求方法:{context.Request.Method}");
            Console.WriteLine($"请求路径:{context.Request.Path}{context.Request.QueryString}");
            // 如果需要记录Body,取消注释以下代码即可
            // context.Request.Body.Position = 0;
            // using var reader = new StreamReader(context.Request.Body, leaveOpen: true);
            // var bodyStr = await reader.ReadToEndAsync();
            // Console.WriteLine($"请求体:{bodyStr}");
            // context.Request.Body.Position = 0;
        }
    }
    catch (Exception ex)
    {
        // 捕获未处理异常,记录信息
        Console.WriteLine($"异常类型:{ex.GetType().Name},异常信息:{ex.Message}");
        Console.WriteLine($"请求方法:{context.Request.Method}");
        Console.WriteLine($"请求路径:{context.Request.Path}{context.Request.QueryString}");
        // 如果需要记录Body,取消注释以下代码即可
        // context.Request.Body.Position = 0;
        // using var reader = new StreamReader(context.Request.Body, leaveOpen: true);
        // var bodyStr = await reader.ReadToEndAsync();
        // Console.WriteLine($"请求体:{bodyStr}");
        // context.Request.Body.Position = 0;
        // 重新抛出异常,让后续异常处理中间件可以正常处理响应
        throw;
    }
});

方案2:使用内置异常处理机制(更简便)

直接通过配置UseExceptionHandler的回调实现,不需要自定义完整中间件:

app.UseExceptionHandler(appBuilder =>
{
    appBuilder.Run(async context =>
    {
        var exception = context.Features.Get<Microsoft.AspNetCore.Diagnostics.IExceptionHandlerFeature>()?.Error;
        if (exception != null)
        {
            // 此处记录逻辑和上述中间件逻辑完全一致
            Console.WriteLine($"异常信息:{exception.Message}");
            Console.WriteLine($"请求URL:{context.Request.GetEncodedUrl()}");
        }
        // 可自定义返回给前端的错误响应
        context.Response.StatusCode = 500;
        await context.Response.WriteAsJsonAsync(new { msg = "系统异常" });
    });
});

注意:如果需要记录请求体,必须在所有读取请求体的中间件之前调用context.Request.EnableBuffering(),否则请求体读取一次后就无法再次读取。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 10:54:01