2016-07-12 14 views
7

Ich habe einen benutzerdefinierten Ausnahmefilter basierend auf diesem Blogpost https://blog.kloud.com.au/2016/03/23/aspnet-core-tips-and-tricks-global-exception-handling/ implementiert.Erhalten Sie Zeilennummer, wo Ausnahme in ASP.NET Core aufgetreten ist

Ich habe jetzt festgestellt, dass ich nicht den Dateinamen oder die Zeilennummer, wo die Ausnahme von StackFrame aufgetreten ist, erhalten kann; der Wert für die Methode GetFileLineNumber immer 0.

Ein kurzes Beispiel von dem, was ich versuchte:

StackTrace trace = new StackTrace(exception, true); 
StackFrame[] stackFrames = trace.GetFrames(); 
if (stackFrames != null) { 
foreach (StackFrame traceFrame in stackFrames) { 
    sourceFile = traceFrame.GetFileName(); 
    sourceLineNumber = traceFrame.GetFileLineNumber(); 
    } 
} 

nur zu erwähnen: GetFileName auch null zurück, aber ich kann den Namespace und Klassennamen von verschiedenen Standorten erhalten, Es ist also kein Problem.

Irgendwo bemerkt, dass ich die PDB-Datei auf dem Ordner dafür haben sollte, um zu arbeiten, und ich habe überprüft, dass ich es bereits habe. Und selbst wenn es funktioniert, sollte dies auch in der Produktionsumgebung funktionieren.

Versucht auch mit Caller Information (https://msdn.microsoft.com/en-us/library/mt653988.aspx), aber es gibt ein anderes Problem. Der Ausnahmefilter muss die IExceptionFilter-Schnittstelle implementieren und seine Methode verwenden. Daher kann ich die Attribute nicht hinzufügen, auch wenn sie optional sind.

Hier ist der Code Teil von Startup.cs:

public void ConfigureServices(IServiceCollection services) { 
... 
services.AddMvc(config => { 
    config.Filters.Add(new ApplicationExceptionFilter()); 
}); 
} 

Und hier ist der benutzerdefinierte Filter

public class ApplicationExceptionFilter : IExceptionFilter { 
public void OnException(ExceptionContext context) { 
    ApplicationExceptionHandler.handleException(context.HttpContext, context.Exception); 
} 
} 

Und was habe ich versucht war, die Anrufer-Informationen für das Erhalten:

public void OnException(ExceptionContext context, 
[System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0) { 

Aber das wird nicht funktionieren, da es die Schnittstelle nicht mehr implementiert.

Wie kann ich die Zeilennummer erhalten, während die Ausnahmen an einem einzigen Ort behandelt werden?


angenommen, dass mein Problem ist die Tatsache, dass ich nicht die Zeilennummer von Stack-Trace immer und reproduziert das Problem mit:

public ActionResult ServerError() { 
Int32 x = 0; 
try { 
    return Content((1/x).ToString()); 
} catch (Exception ex) { 
    StackTrace trace = new StackTrace(ex, true); 
    StackFrame[] stackFrames = trace.GetFrames(); 
    if (stackFrames != null) { 
    foreach (StackFrame traceFrame in stackFrames) { 
    String sourceFile = traceFrame.GetFileName(); 
    int sourceLineNumber = traceFrame.GetFileLineNumber(); 
    } 
    } 
} 
return Content(""); 
} 

Noch keine Werte für source (es ist null) oder sourceLineNumber bekommen (Es ist 0).

+0

aka In optimierten Code. Release-Builds, der Assembly-Code/IL-Code stimmt möglicherweise nicht mehr mit den Zeilennummern überein. –

+0

@Thomas Es gibt einen Unterschied zwischen nicht übereinstimmen und sie sind absolut null. – DavidG

+0

@Thomas gibt es keine Zeilennummer in Release erstellt – user3185569

Antwort

-1

Werfen Sie einen Blick auf die DeveloperErrorPageMiddlewareimplementation:

private IEnumerable<ErrorDetails> GetErrorDetails(Exception ex) 
    { 
     for (var scan = ex; scan != null; scan = scan.InnerException) 
     { 
      var stackTrace = ex.StackTrace; 
      yield return new ErrorDetails 
      { 
       Error = scan, 
       StackFrames = StackTraceHelper.GetFrames(ex) 
        .Select(frame => GetStackFrame(frame.MethodDisplayInfo.ToString(), frame.FilePath, frame.LineNumber)) 
      }; 
     }; 
    } 

    // make it internal to enable unit testing 
    internal StackFrame GetStackFrame(string method, string filePath, int lineNumber) 
    { 
     var stackFrame = new StackFrame 
     { 
      Function = method, 
      File = filePath, 
      Line = lineNumber 
     }; 

     if (string.IsNullOrEmpty(stackFrame.File)) 
     { 
      return stackFrame; 
     } 

     IEnumerable<string> lines = null; 
     if (File.Exists(stackFrame.File)) 
     { 
      lines = File.ReadLines(stackFrame.File); 
     } 
     else 
     { 
      // Handle relative paths and embedded files 
      var fileInfo = _fileProvider.GetFileInfo(stackFrame.File); 
      if (fileInfo.Exists) 
      { 
       // ReadLines doesn't accept a stream. Use ReadLines as its more efficient 
       // relative to reading lines via stream reader 
       if (!string.IsNullOrEmpty(fileInfo.PhysicalPath)) 
       { 
        lines = File.ReadLines(fileInfo.PhysicalPath); 
       } 
       else 
       { 
        lines = ReadLines(fileInfo); 
       } 
      } 
     } 

     if (lines != null) 
     { 
      ReadFrameContent(stackFrame, lines, stackFrame.Line, stackFrame.Line); 
     } 

     return stackFrame; 
    } 
+0

Wie hilft das bei der gestellten Frage? – DavidG

+0

Hilft irgendwie weiter. Ich habe jetzt bemerkt, dass ich die Zeilennummern auf DeveloperExceptionPage bekomme. Betrachtet man jedoch die Quellen, scheint es von der Stack-Spur zu kommen, was ich nicht bin. – mepsi

Verwandte Themen