C# 记录任何类型异常的所有异常信息

C# 记录任何类型异常的所有异常信息,c#,asp.net-mvc,entity-framework,exception,log4net,C#,Asp.net Mvc,Entity Framework,Exception,Log4net,我正在使用C#、ASP.NET MVC Web Api、实体框架和.NET Framework 4.0进行开发 我有以下代码记录异常: public void LogCompleteException( string controllerName, string actionName, Exception exception) { string exceptionMessage = string.Empty; Exception e = exceptio

我正在使用C#、ASP.NET MVC Web Api、实体框架和.NET Framework 4.0进行开发

我有以下代码记录异常:

public void LogCompleteException(
    string controllerName,
    string actionName,
    Exception exception)
{
    string exceptionMessage = string.Empty;

    Exception e = exception;
    if (e.InnerException == null)
        e = null;
    else
        while (e.InnerException != null) e = e.InnerException;

    if (e == null)
        exceptionMessage = exception.Message;
    else
        exceptionMessage = string.Format("{0}\n\rInnerException: {1}", exception.Message, e.Message);

    _logger.ErrorFormat(
        LogTextFormatString,
        ExceptionText,
        controllerName,
        actionName,
        exceptionMessage);
}
但在我的日志文件中,我发现:

一个或多个实体的验证失败。看见 “EntityValidationErrors”属性以获取更多详细信息

当我写“请参阅EntityValidationErrors属性以了解更多详细信息”时,我只展示了一个示例,其中我没有记录重要属性

有很多例外情况;但是使用我的方法,我不会记录所有相关信息,因为可能有像“EntityValidationErrors”这样的属性我不会记录

当我传递异常来记录它时,我不知道它有什么属性,也不知道如何记录它的每个属性

您知道完整记录异常的方法吗?我的代码不会出现
EntityValidationErrors
属性或任何其他重要属性的长异常


我正在用log4net进行日志记录。

因为内部异常本身就是一个异常,也许您可以递归并重用已有的方法:

if (e.InnerException != null)
{
    LogCompleteException(controllerName, actionName, e.InnerException);
}
但是,如果这确实有效,您仍然会缺少EntityValidationErrors

我最近使用的另一种方法是在异常发生时显式捕获并记录异常:

try
{
    db.Add(something);
    db.SaveChanges();
}
catch (DbEntityValidationException ex)
{
    StringBuilder sb = new StringBuilder();

    // collect some extra info about the exception before logging
    foreach (var eve in ex.EntityValidationErrors)
    {
        sb.AppendLine(String.Format("Entity of type \"{0}\" in state \"{1}\" has the following validation errors:", eve.Entry.Entity.GetType().Name, eve.Entry.State));
        foreach (var ve in eve.ValidationErrors)
        {
            sb.AppendLine(String.Format("Property: \"{0}\", Error: \"{1}\"", ve.PropertyName, ve.ErrorMessage));
        }
    }

    logger.Error("There was an error while trying to parse and save something!\n" + sb.ToString(), ex);
}
如果需要Exception.Data字典条目,还可以添加这些条目:

foreach (DictionaryEntry entry in ex.Data)
{
    // you will want to use a StringBuilder instead of concatenating strings if you do this
    exceptionMessage = exceptionMessage + string.Format("Exception.Data[{0}]: {1}", entry.Key, entry.Value);
}

至于自定义异常类的属性,就像EntityValidationErrors一样,我只需要捕获和解析它们出现的地方。否则,您将不得不在每个异常类型上重写ToString(),或者使用一些反射黑客来枚举所有属性,这些属性会用您不关心的属性将日志弄得乱七八糟。

您可以使用和。Elmah日志捕获所有异常,并可以将它们记录到log4net实例

我假设日志记录是通过log4net完成的?是的,我使用log4net进行日志记录。为什么不使用exception.ToString()?您看到了吗?假设您不想捕获
DbEntityValidationException
异常并自己创建完整的错误消息,这样安全吗?@Michael
DbEntityValidationException
异常这只是一个例子,我可以得到很多种异常,但没有任何重要信息。我想我在我的问题中没有解释清楚。当我写“请参阅'EntityValidationErrors'属性以了解更多详细信息”时,我展示了一个我没有记录重要属性的示例。有很多例外情况,用我的方法,我没有登录所有这些信息。你能给出更多“重要属性”的例子吗?绝大多数异常将此数据存储在中。尽管存在异常值(例如EntityValidationErrors),您可能需要使用反射来枚举所有异常的属性,或者事先显式检查它们。对于这些异常值,最好的办法是在抛出时处理它们,如在我的示例代码IMO中。我不能给您更多的“导入属性”示例,因为我不知道我必须记录哪种异常。这就是为什么我要求完全记录一个异常,因为我想用信息记录任何属性。顺便说一下,我用这一行
记录最内部的
inereException
,而(e.InnerException!=null)e=e.InnerException