.NET: How to convert Exception to string?

前端 未结 10 603
隐瞒了意图╮
隐瞒了意图╮ 2021-01-30 10:47

When an exception is thrown (while debugging in the IDE), i have the opportunity to view details of the exception:

相关标签:
10条回答
  • 2021-01-30 10:51

    ErrorCode is specific to ExternalException, not Exception and LineNumber and Number are specific to SqlException, not Exception. Therefore, the only way to get these properties from a general extension method on Exception is to use reflection to iterate over all of the public properties.

    So you'll have to say something like:

    public static string GetExceptionDetails(this Exception exception) {
        var properties = exception.GetType()
                                .GetProperties();
        var fields = properties
                         .Select(property => new { 
                             Name = property.Name,
                             Value = property.GetValue(exception, null)
                         })
                         .Select(x => String.Format(
                             "{0} = {1}",
                             x.Name,
                             x.Value != null ? x.Value.ToString() : String.Empty
                         ));
        return String.Join("\n", fields);
    }
    

    (Not tested for compliation issues.)

    .NET 2.0 compatible answer:

    public static string GetExceptionDetails(this Exception exception) 
    {
        PropertyInfo[] properties = exception.GetType()
                                .GetProperties();
        List<string> fields = new List<string>();
        foreach(PropertyInfo property in properties) {
            object value = property.GetValue(exception, null);
            fields.Add(String.Format(
                             "{0} = {1}",
                             property.Name,
                             value != null ? value.ToString() : String.Empty
            ));    
        }         
        return String.Join("\n", fields.ToArray());
    }
    
    0 讨论(0)
  • 2021-01-30 10:52

    For people who don't want to mess with overriding, this simple non-intrusive method might be enough:

        public static string GetExceptionDetails(Exception exception)
        {
            return "Exception: " + exception.GetType()
                + "\r\nInnerException: " + exception.InnerException
                + "\r\nMessage: " + exception.Message
                + "\r\nStackTrace: " + exception.StackTrace;
        }
    

    It does not show the SQLException-specific details you want, though...

    0 讨论(0)
  • 2021-01-30 10:53

    You will probably have to manually construct that string by concatenating the various fields you are interested in.

    0 讨论(0)
  • 2021-01-30 10:55

    I first tried Jason's answer (at the top), which worked pretty well, but I also wanted:

    • To loop iteratively through inner exceptions and indent them.
    • Ignore null properties and increases readability of the output.
    • It includes the metadata in the Data property. (if any) but excludes the Data property itself. (its useless).

    I now use this:

        public static void WriteExceptionDetails(Exception exception, StringBuilder builderToFill, int level)
        {
            var indent = new string(' ', level);
    
            if (level > 0)
            {
                builderToFill.AppendLine(indent + "=== INNER EXCEPTION ===");                
            }
    
            Action<string> append = (prop) =>
                {
                    var propInfo = exception.GetType().GetProperty(prop);
                    var val = propInfo.GetValue(exception);
    
                    if (val != null)
                    {
                        builderToFill.AppendFormat("{0}{1}: {2}{3}", indent, prop, val.ToString(), Environment.NewLine);
                    }
                };
    
            append("Message");
            append("HResult");
            append("HelpLink");
            append("Source");
            append("StackTrace");
            append("TargetSite");
    
            foreach (DictionaryEntry de in exception.Data)
            {
                builderToFill.AppendFormat("{0} {1} = {2}{3}", indent, de.Key, de.Value, Environment.NewLine);
            }
    
            if (exception.InnerException != null)
            {
                WriteExceptionDetails(exception.InnerException, builderToFill, ++level);
            }
        }
    

    Call like this:

            var builder = new StringBuilder();
            WriteExceptionDetails(exception, builder, 0);
            return builder.ToString();
    
    0 讨论(0)
  • 2021-01-30 10:59

    For displaying some details to user you should use ex.Message. For displaying to developers you will probably need ex.Message and ex.StackTrace.

    There is no 'secret' method, you could consider Message property to be best fit for user friendly message.

    Also be careful that in some case you may have inner exception in exception you catch which would be also useful to log.

    0 讨论(0)
  • 2021-01-30 11:08

    If you call ToString on Exception object, you get the class name appended by the message, followed by inner exception and then the stack trace.

    className + message + InnerException + stackTrace
    

    Given that, InnerException and StackTrace are only added if they are not null. Also, the fields you have mentioned in the screenshot are not part of standard Exception class. Yes, exception does offer a public property called "Data", that contain additional user-defined information about the exception.

    0 讨论(0)
提交回复
热议问题