无法在自定义 C# 异常中访问 StackTrace
Unable to access StackTrace in custom C# Exception
我最近尝试为我的 Web API 设置一个日志系统。我决定我要创建自定义异常 classes 可以抛出然后由我的 GlobalExceptionHandler 记录。但是,我在访问自定义异常对象的 StackTrace 时遇到了一些问题。
我设置了一个名为 LoggableException 的自定义异常 class,我将其用作我要记录到数据库的所有自定义异常的父 class。
public class LoggableException : Exception
{
public LogEntity Log { get; set; }
public string ResponseMessage { get; set; }
public LoggableException(LogEntity _log, string _responseMessage) : base(_log.ExceptionMessage)
{
Log = _log;
Log.Level = LogLevel.Warn;
Log.Exception = GetType().Name;
Log.StackTrace = StackTrace.Substring(0, 1000);
ResponseMessage = _responseMessage;
}
}
这是我的自定义 LoggableExceptions 之一的示例:
public class InvalidPassword : LoggableException
{
public InvalidPassword(string email) : base(new LogEntity()
{
ExceptionMessage = $"Invalid password. email: {email}",
ResponseCode = (int) HttpStatusCode.Unauthorized
}, $"Unknown email or incorrect password.")
{ }
}
但是,似乎每当我抛出这些 LoggableExceptions 之一时,<System.NullReferenceException: Object reference not set to an instance of an object.
也会在 Log.StackTrace = StackTrace.Substring(0, 1000);
处抛出。我这样做是为了不在我的数据库中存储巨大的 StackTrace 字符串,但 StackTrace 始终为空。我假设如果我调用基本构造函数它会自动实例化 StackTrace,但我想我错了。谁能向我解释我在这里做错了什么?我对 C# 还是比较陌生。
NullReference 异常被抛出,因为您正在访问构造函数本身内部构建的实例的 StackTrace 属性。
你应该使用
Log.StackTrace = StackTrace?.Substring(0, 1000);
或
if(StackTrace!=null) Log.StackTrace=StackTrace.Substring(0, 1000);
而是确保 this.StackTrace 已经实例化
您应该注意当 StackTrace 长度小于 1000 个字符时可能抛出的 ArgumentOutOfRangeException
这已经很老了,但还没有发布实际的解决方案。我还想在每个新的自定义异常上自动创建一个系统日志(即使这不是“最佳实践”),这对我有用。
虽然 Stacktrace 尚未在您的构造函数中初始化,但您可以 create a new instance of StackTrace。
public class LoggableException : Exception
{
public LogEntity Log { get; set; }
public string ResponseMessage { get; set; }
public LoggableException(LogEntity _log, string _responseMessage) : base(_log.ExceptionMessage)
{
Log = _log;
Log.Level = LogLevel.Warn;
Log.Exception = GetType().Name;
Log.StackTrace = (new System.Diagnostics.StackTrace()).ToString();
if (Log.StackTrace.Length > 1000)
Log.StackTrace = Log.StackTrace.Substring(0, 1000);
ResponseMessage = _responseMessage;
}
}
这应该可以满足您的要求。
唯一的问题是您的 LoggableException 构造函数也会在那里(第 0 帧)突然出现,但您始终可以循环所有帧来创建 Stactrace 字符串,根据需要格式化数据并跳过第 0 帧。
我最近尝试为我的 Web API 设置一个日志系统。我决定我要创建自定义异常 classes 可以抛出然后由我的 GlobalExceptionHandler 记录。但是,我在访问自定义异常对象的 StackTrace 时遇到了一些问题。
我设置了一个名为 LoggableException 的自定义异常 class,我将其用作我要记录到数据库的所有自定义异常的父 class。
public class LoggableException : Exception
{
public LogEntity Log { get; set; }
public string ResponseMessage { get; set; }
public LoggableException(LogEntity _log, string _responseMessage) : base(_log.ExceptionMessage)
{
Log = _log;
Log.Level = LogLevel.Warn;
Log.Exception = GetType().Name;
Log.StackTrace = StackTrace.Substring(0, 1000);
ResponseMessage = _responseMessage;
}
}
这是我的自定义 LoggableExceptions 之一的示例:
public class InvalidPassword : LoggableException
{
public InvalidPassword(string email) : base(new LogEntity()
{
ExceptionMessage = $"Invalid password. email: {email}",
ResponseCode = (int) HttpStatusCode.Unauthorized
}, $"Unknown email or incorrect password.")
{ }
}
但是,似乎每当我抛出这些 LoggableExceptions 之一时,<System.NullReferenceException: Object reference not set to an instance of an object.
也会在 Log.StackTrace = StackTrace.Substring(0, 1000);
处抛出。我这样做是为了不在我的数据库中存储巨大的 StackTrace 字符串,但 StackTrace 始终为空。我假设如果我调用基本构造函数它会自动实例化 StackTrace,但我想我错了。谁能向我解释我在这里做错了什么?我对 C# 还是比较陌生。
NullReference 异常被抛出,因为您正在访问构造函数本身内部构建的实例的 StackTrace 属性。
你应该使用
Log.StackTrace = StackTrace?.Substring(0, 1000);
或
if(StackTrace!=null) Log.StackTrace=StackTrace.Substring(0, 1000);
而是确保 this.StackTrace 已经实例化
您应该注意当 StackTrace 长度小于 1000 个字符时可能抛出的 ArgumentOutOfRangeException
这已经很老了,但还没有发布实际的解决方案。我还想在每个新的自定义异常上自动创建一个系统日志(即使这不是“最佳实践”),这对我有用。
虽然 Stacktrace 尚未在您的构造函数中初始化,但您可以 create a new instance of StackTrace。
public class LoggableException : Exception
{
public LogEntity Log { get; set; }
public string ResponseMessage { get; set; }
public LoggableException(LogEntity _log, string _responseMessage) : base(_log.ExceptionMessage)
{
Log = _log;
Log.Level = LogLevel.Warn;
Log.Exception = GetType().Name;
Log.StackTrace = (new System.Diagnostics.StackTrace()).ToString();
if (Log.StackTrace.Length > 1000)
Log.StackTrace = Log.StackTrace.Substring(0, 1000);
ResponseMessage = _responseMessage;
}
}
这应该可以满足您的要求。
唯一的问题是您的 LoggableException 构造函数也会在那里(第 0 帧)突然出现,但您始终可以循环所有帧来创建 Stactrace 字符串,根据需要格式化数据并跳过第 0 帧。