我希望有一个函数,当给它一个异常时,它将提取有关该异常的所有信息,然后将其写入数据库。
在转到.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。我看了一下我提取的帧,它们不再有任何信息。对于FileName
和LineNumber
之类的值,它们为null。对于MethodName
和ClassName
之类的东西,值在那里但错误的。
我会使用以下代码使我的项目崩溃:
public class TestController : Controller
{
[HttpGet]
[AllowAnonymous]
public string ErrorHandling()
{
var a = int.Parse("fail parsing on purpose");
return a.ToString();
}
}
MethodName
的值最终为StringToNumber
,ClassName
的值为System.Number
我似乎无法在网上找到有关这是为什么以及如何获取异常详细信息的任何信息。
编辑:
我认为列出我如何处理异常也可能很有用。我已经编写了一个自定义中间件错误异常处理程序,该异常处理程序与此SO帖子中的处理程序非常相似:
https://stackoverflow.com/a/48625298/2371128
编辑2: 它正在DEBUG模式下运行。
答案 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()
};