获取异常详细信息

时间:2018-06-24 18:35:00

标签: c# asp.net-core asp.net-core-mvc asp.net-core-2.0

我希望有一个函数,当给它一个异常时,它将提取有关该异常的所有信息,然后将其写入数据库。

在转到.NET Core 2之前,我可以通过以下方式进行此操作:

var details = new ErrorDetails();
if (ex == null) return details;
var st = new StackTrace(ex, true);
var frames = st.GetFrames();
if (frames != null && frames.Length > 0)
{
    var errorDetails = frames.Select(frame => new ErrorDetails
    {
        FileName = frame.GetFileName(),
        LineNumber = frame.GetFileLineNumber().ToString(),
        MethodName = frame.GetMethod().Name,
        ClassName = frame.GetMethod().DeclaringType.FullName
    });

    return errorDetails.FirstOrDefault();
}
return details;

自从将我的项目切换到.NET Core 2以来,此代码都会返回,其中大多数信息为null / default。我看了一下我提取的帧,它们不再有任何信息。对于FileNameLineNumber之类的值,它们为null。对于MethodNameClassName之类的东西,值在那里但错误的。

我会使用以下代码使我的项目崩溃:

public class TestController : Controller
{
    [HttpGet]
    [AllowAnonymous]
    public string ErrorHandling()
    {
        var a = int.Parse("fail parsing on purpose");
        return a.ToString();
    }
}

MethodName的值最终为StringToNumberClassName的值为System.Number

我似乎无法在网上找到有关这是为什么以及如何获取异常详细信息的任何信息。

编辑:

我认为列出我如何处理异常也可能很有用。我已经编写了一个自定义中间件错误异常处理程序,该异常处理程序与此SO帖子中的处理程序非常相似:

https://stackoverflow.com/a/48625298/2371128

编辑2: 它正在DEBUG模式下运行。

2 个答案:

答案 0 :(得分:0)

将以下内容添加到您的Startup.cs

app.UseExceptionHandler(
         options =>
         {
             options.Run(
             async context =>
             {
                 var ex = context.Features.Get<IExceptionHandlerFeature>();
                 if (ex != null)
                 {
                     try
                     {
                         await System.Threading.Tasks.Task.Run(async () =>
                          {
                              var builder = new DbContextOptionsBuilder<DBContext>();
                              builder.UseSqlServer(_config["ConnectionStrings:ContextConnection"]);
                              var _context = new DBContext(_config, builder.Options, httpContextAccessor);
                              //Log to DB
                              await repository.LogError(_context, ex.Error.Message, $"{ex.Error.InnerException?.Message}<br/>{ex.Error.StackTrace}");
                          });

                     }
                     finally
                     {
                         //Optional
                         await repository.SendMailToAdmin(ex.Error.Message, $"{ex.Error.InnerException?.Message}<br/>{ex.Error.StackTrace}");
                     }

                     context.Response.Redirect("/app/Errors/500");
                 }
             });
         }
        );

// ErrorLog.cs

 public class ErrorLog
{
    public int Id { get; set; }
    [Required]
    [StringLength(500)]
    public string Error { get; set; }
    [Required]
    [StringLength(4000)]
    public string Details { get; set; }

    public int? UserId { get; set; }
    public int CreatedBy { get; set; }
    public DateTime CreatedDate { get; set; }
}

答案 1 :(得分:0)

这是我的建议:

public class ExceptionDetail
{
    public string Message { get; set; }

    public string InnerExceptionMessage { get; set; }

    public string StackTrace { get; set; }

    public IEnumerable<string> StackTraceLines { get; set; }

    public string Target { get; set; }

    public string Source { get; set; }
}


var exDetail = new ExceptionDetail
{
    Message = exception.Message,
    InnerExceptionMessage = exception.InnerException?.Message,
    Source = exception.Source,
    StackTrace = exception.StackTrace,
    StackTraceLines = exception.StackTrace.Split(new[] { Environment.NewLine }, StringSplitOptions.None).ToList(),
    Target = exception.TargetSite.ToString()
};