.NET8中ASP.NET Core错误处理:如何获取请求URL等信息
解决ASP.NET Core 8异常处理器中获取原始请求信息的问题
核心逻辑
当启用app.UseExceptionHandler("/Home/Error")时,异常触发后会触发内部重定向,此时当前HttpContext指向的是错误页面的请求,而非原始出错请求。原始请求的所有信息需要从异常处理特性对象中提取,不能直接使用当前上下文。
具体解决方案
1. 获取原始请求URL
通过IExceptionHandlerPathFeature获取原始请求上下文,拼接完整URL:
public class ErrorHandler : IExceptionHandler { private readonly IHttpContextAccessor _httpContextAccessor; private readonly ILogger<ErrorHandler> _logger; public ErrorHandler(IHttpContextAccessor httpContextAccessor, ILogger<ErrorHandler> logger) { _httpContextAccessor = httpContextAccessor; _logger = logger; } public async ValueTask<bool> TryHandleAsync(HttpContext httpContext, Exception exception, CancellationToken cancellationToken) { // 提取原始请求特性 var exceptionPathFeature = httpContext.Features.Get<IExceptionHandlerPathFeature>(); if (exceptionPathFeature != null) { var originalReq = exceptionPathFeature.HttpContext.Request; // 拼接完整原始URL var originalFullUrl = $"{originalReq.Scheme}://{originalReq.Host}{originalReq.Path}{originalReq.QueryString}"; _logger.LogError("原始请求URL: {Url}", originalFullUrl); } // 后续异常处理逻辑 return true; } }
2. 读取原始表单数据
原始请求的表单流默认只能读取一次,直接读取会导致崩溃,需要提前缓存请求流:
第一步:添加请求体缓存中间件
public class RequestBodyCacheMiddleware { private readonly RequestDelegate _next; public RequestBodyCacheMiddleware(RequestDelegate next) { _next = next; } public async Task InvokeAsync(HttpContext context) { // 启用请求流缓存,允许多次读取 context.Request.EnableBuffering(); await _next(context); } }
第二步:在Program.cs中注册中间件(必须在UseExceptionHandler之前)
var builder = WebApplication.CreateBuilder(args); // 注册必要服务 builder.Services.AddHttpContextAccessor(); builder.Services.AddExceptionHandler<ErrorHandler>(); var app = builder.Build(); // 注册缓存中间件,确保在异常处理器之前执行 app.UseMiddleware<RequestBodyCacheMiddleware>(); app.UseExceptionHandler("/Home/Error"); // 其他中间件配置... app.Run();
第三步:在ErrorHandler中读取表单数据
var originalReq = exceptionPathFeature.HttpContext.Request; if (originalReq.HasFormContentType) { // 重置流位置到起始点 originalReq.Body.Position = 0; var formData = await originalReq.ReadFormAsync(cancellationToken); // 遍历记录表单字段 foreach (var key in formData.Keys) { _logger.LogError("表单字段: {Key}, 值: {Value}", key, formData[key]); } }
3. 获取原始Referrer请求头
同样通过IExceptionHandlerPathFeature中的原始请求上下文获取:
var originalReq = exceptionPathFeature.HttpContext.Request; var referrer = originalReq.Headers.Referer.ToString(); if (!string.IsNullOrWhiteSpace(referrer)) { _logger.LogError("Referrer: {Referrer}", referrer); }
注意事项
- 中间件顺序不可颠倒:
RequestBodyCacheMiddleware必须在UseExceptionHandler之前注册,才能确保原始请求流被缓存。 - 若API接收JSON请求体,同样可以用
EnableBuffering()缓存流,之后读取RequestBody获取原始JSON内容。 - 生产环境需对日志中的敏感表单数据进行脱敏处理,避免信息泄露。
内容的提问来源于stack exchange,提问作者Leo Muller
相关产品推荐
相关产品推荐

