在 Asp.Net Core 中记录中间件,然后使用 UseExceptionHandler



我有一个Asp.Net.Core应用程序,其中必须有一些日志记录,今天我尝试添加异常处理中间件。我用过UseExceptionHandler它来自asp.net Diagonstics.问题是当我的日志记录中间件在ExceptionHandler中间件之后时

app.UseExceptionHandler("/error");
app.UseSerilogMiddleware();

当出现一些异常时,它不会将我重定向到我的自定义错误页面。

public async Task Invoke(HttpContext httpContext)
        {
            if (httpContext == null)
            {
                Log.Write(LogEventLevel.Fatal, "No HTTP context found!");
            }
            HttpRequest request = httpContext.Request;
            var logger = GetExtendedLogger(request);
            var stopwatchStart = Stopwatch.GetTimestamp();
            try
            {
                var originalResponseBody = httpContext.Response.Body;
                using (MemoryStream stream = new MemoryStream())
                {
                    **httpContext.Response.Body = stream;**
                    await _next(httpContext);
                    stream.Seek(0, SeekOrigin.Begin);
                    var responseBody = new StreamReader(stream).ReadToEnd();
                    var elapsedMs = GetElapsedMilliseconds(stopwatchStart, Stopwatch.GetTimestamp());
                    var statusCode = httpContext.Response?.StatusCode;
                    var level = GetLogEventLevel(statusCode);
                    var log = Log
                    .ForContext("RequestHeaders", httpContext.Request.Headers.ToDictionary(h => h.Key, h => h.Value.ToString()), destructureObjects: true)
                    .ForContext("RequestHost", httpContext.Request.Host)
                    .ForContext("RequestProtocol", httpContext.Request.Protocol);
                    logger.Write(level, MessageTemplate, httpContext.Request.Method, httpContext.Request.Path, statusCode, elapsedMs, responseBody);
                    stream.Seek(0, SeekOrigin.Begin);
                    await stream.CopyToAsync(originalResponseBody);
                }
            }
            // Never caught, because LogException() returns false.
            catch (Exception ex) when (AddExceptionLogEntry(logger, httpContext, GetElapsedMilliseconds(stopwatchStart, Stopwatch.GetTimestamp()), ex))
            {
            }
        }' 

这是日志记录中间件的一部分,但是我发现了导致问题的原因,但我没有解释。问题出在这一行httpContext.Response.Body = stream;当我删除将响应正文设置为流时,一切正常。

附言日志记录方法从此处复制粘贴

TL;DR:在UseExceptionHandler之前不要写入流,否则错误中间件无法写入重定向标头。

stream.Seek(0, SeekOrigin.Begin);
await stream.CopyToAsync(originalResponseBody);

在调用异常中间件之前,您正在写入响应流,因此重定向不起作用。HTTP 中的重定向是一种响应,它返回 http 代码 301 或 302,带有带有新 url 的 Location: http://example.com 标头。

但是,当您写入流时,标头已刷新,无法再更改。

相关内容

  • 没有找到相关文章

最新更新