2017-06-14 5 views
0

Ich habe Asp.Net.Core App, in denen es einige Protokollierung sein muss, heute habe ich versucht, Ausnahmebehandlung Middleware hinzufügen. Ich habe UseExceptionHandler verwendet, die von asp.net Diagonstics ist. Das Problem war, dass, wenn meine Logging-Middleware war nach ExceptionHandler MiddlewareLogging Middleware in Asp.Net Core und danach mit UseExceptionHandler

app.UseExceptionHandler("/error"); 

app.UseSerilogMiddleware(); 

Es wasnot redirectig mich auf meine benutzerdefinierte Fehlerseite, wenn es einige Ausnahme war.

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)) 
      { 
      } 
     }' 

Dies ist Teil der Logging-Middleware, jedoch fand ich heraus, was das Problem verursacht wurde, aber ich habe keine Erklärung dafür. Das Problem ist in dieser Zeile httpContext.Response.Body = stream;, wenn ich entferne die Antwort Körper in den Stream alles funktioniert gut.

P.S. Die Logging-Methode wird Kopie von here klebte

Antwort

1

TL; DR: Verwenden Sie in den Stream nicht schreiben, bevor UseExceptionHandler sonst der Fehler Middleware-Header umleiten nicht schreiben kann.

Sie schreiben in den Antwort-Stream, bevor die Ausnahme Middleware aufgerufen wird, so dass eine Weiterleitung nicht funktionieren kann. Eine Umleitung in HTTP ist eine Antwort, die den HTTP-Code 301 oder 302 mit einem Location: http://example.com Header mit der neuen URL zurückgibt.

Wenn Sie jedoch in den Stream schreiben, sind die Header bereits geleert und können nicht mehr geändert werden.

+0

Ich sehe .. aber warum 'httpContext.Response.Body = stream; entfernen' diese Zeile, wo der Körper auf den neu erstellten Stream setzt, behebt dieses Problem? –

+1

Es ist einfach: Weil, wenn Sie 'httpContext.Response.Body = stream;' entfernen, die zugrunde liegende Middleware niemals etwas in den Speicher-Stream schreibt, so ist der Speicher-Stream ** EMPTY **. Wenn Sie zu Ihrer Middleware zurückkehren, erwarten Sie stream.CopyToAsync (originalResponseBody); 'schreiben Sie auch nichts, weil es 0 Bytes Daten enthält, also wird nie etwas über die Leitung an den Client gesendet, was letztendlich die Exception Middleware erlaubt es zu schreiben ist Header – Tseng

+1

Fazit: Sie müssen Ihre Middleware in zwei teilen. Erste Middleware, die try/catch mit 'AddExceptionLogEntry' verwendet, das ** AFTER ** die Ausnahmemiddleware und eine andere Middlware registriert ist, die den Speicherstream verwendet und die erfolgreichen Aufrufe protokolliert, die Sie vor ** der Ausnahmemiddleware platzieren – Tseng

Verwandte Themen