When an exception is thrown (while debugging in the IDE), i have the opportunity to view details of the exception:
But in code if i call exception.ToString()
i do not get to see those useful details:
System.Data.SqlClient.SqlException (0x80131904): Could not find stored procedure 'FetchActiveUsers'. [...snip stack trace...]
But Visual Studio has some magic where it can copy the exception to the clipboard:
Which gives the useful details:
System.Data.SqlClient.SqlException was unhandled by user code Message=Could not find stored procedure 'FetchActiveUsers'. Source=.Net SqlClient Data Provider ErrorCode=-2146232060 Class=16 LineNumber=1 Number=2812 Procedure="" Server=vader State=62 StackTrace: [...snip stack trace...] InnerException:
Well i want that!
What would be the contents of:
String ExceptionToString(Exception ex) { //todo: Write useful routine return ex.ToString(); }
that can accomplish the same magic. Is there a .NET function built in somewhere? Does Exception
have a secret method somewhere to convert it to a string?
ToString returns a representation of the current exception that is intended to be understood by humans. Where the exception contains culture-sensitive data, the string representation returned by ToString is required to take into account the current system culture.
To catch an exception that an async task throws, place the await expression in a try block, and catch the exception in a catch block. Uncomment the throw new Exception line in the example to demonstrate exception handling. The task's IsFaulted property is set to True , the task's Exception.
The Exception. ToString() method will give a much more verbose output, containing the exception type, the message (from before), a stack trace, and all of these things again for nested/inner exceptions.
If you want information about all exceptions then use exception. ToString() . It will collect data from all inner exceptions. If you want only the original exception then use exception.
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()); }
I first tried Jason's answer (at the top), which worked pretty well, but I also wanted:
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();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With