Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

.NET: How to convert Exception to string?

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

enter image description here

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:

enter image description here

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?

like image 282
Ian Boyd Avatar asked Nov 07 '11 16:11

Ian Boyd


People also ask

What does exception ToString return c#?

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.

How do I read an exception message in C#?

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.

Does exception ToString include Stacktrace?

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.

Does exception ToString include inner exception?

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.


2 Answers

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()); } 
like image 141
jason Avatar answered Sep 21 '22 18:09

jason


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(); 
like image 25
Gerben Rampaart Avatar answered Sep 20 '22 18:09

Gerben Rampaart