Today I’ve got another WTF. I found that inner fault exception is not included into outerException.ToString()
try
{
try
{
throw new Exception("Very important inner exception");
}
catch (Exception innerException)
{
var faultException = new FaultException<Exception>(innerException, new FaultReason("Some reason"));
throw new Exception("Outer exception", faultException);
}
}
catch (Exception outerException)
{
Console.WriteLine(outerException.ToString());
}
And the output is
System.Exception: Outer exception ---> System.ServiceModel.FaultException`1[System.Exception]: Some reason
--- End of inner exception stack trace ---
at ConsoleApplication2.Program.Main(String[] args) in c:\Users\Michael\Documents\Visual Studio 2012\Projects\ConsoleApplication2\ConsoleApplication2\Program.cs:line 23
You can see that inner exception message was not passed to the output.
However if you call
outerException.InnerException.ToString()
you will get fault details with inner exception
System.ServiceModel.FaultException`1[System.Exception]: Some reason (Fault Detail is equal to System.Exception: Very important inner exception
at ConsoleApplication2.Program.Main(String[] args) in c:\Users\Michael\Documents\Visual Studio 2012\Projects\ConsoleApplication2\ConsoleApplication2\Program.cs:line 18).
This behavior is very bad. In our current project we have such situation all the time and our Error page is absolutely useless because this important InnerExceptions are being trimmed.
To fix the issue I had to create an extension method
public static string ToStringWithFaultDetails(this Exception exception)
{
if (exception == null)
return "";
var sb = new StringBuilder();
sb.AppendLine(exception.ToString());
var innerException = exception.InnerException;
while (innerException != null)
{
var faultException = innerException as FaultException;
if (faultException != null)
{
sb.AppendLine(string.Format("{0}Inner Fault Exception: {0}{1}", System.Environment.NewLine, faultException.ToStringWithFaultDetails()));
break;
}
innerException = innerException.InnerException;
}
return sb.ToString();
}
If we now modify first program and change line #15
Console.WriteLine(outerException.ToStringWithFaultDetails());
We will not lose inner exception.
System.Exception: Outer exception ---> System.ServiceModel.FaultException`1[System.Exception]: Some reason
--- End of inner exception stack trace ---
at ConsoleApplication2.Program.Main(String[] args) in c:\Users\Michael\Documents\Visual Studio 2012\Projects\ConsoleApplication2\ConsoleApplication2\Program.cs:line 23
Inner Fault Exception:
System.ServiceModel.FaultException`1[System.Exception]: Some reason (Fault Detail is equal to System.Exception: Very important inner exception
at ConsoleApplication2.Program.Main(String[] args) in c:\Users\Michael\Documents\Visual Studio 2012\Projects\ConsoleApplication2\ConsoleApplication2\Program.cs:line 18).