Getting the innermost .NET Exception
- by Rick Strahl
Here's a trivial but quite useful function that I frequently need in dynamic execution of code: Finding the innermost exception when an exception occurs, because for many operations (for example Reflection invocations or Web Service calls) the top level errors returned can be rather generic. A good example - common with errors in Reflection making a method invocation - is this generic error: Exception has been thrown by the target of an invocation In the debugger it looks like this: In this case this is an AJAX callback, which dynamically executes a method (ExecuteMethod code) which in turn calls into an Amazon Web Service using the old Amazon WSE101 Web service extensions for .NET. An error occurs in the Web Service call and the innermost exception holds the useful error information which in this case points at an invalid web.config key value related to the System.Net connection APIs. The "Exception has been thrown by the target of an invocation" error is the Reflection APIs generic error message that gets fired when you execute a method dynamically and that method fails internally. The messages basically says: "Your code blew up in my face when I tried to run it!". Which of course is not very useful to tell you what actually happened. If you drill down the InnerExceptions eventually you'll get a more detailed exception that points at the original error and code that caused the exception. In the code above the actually useful exception is two innerExceptions down. In most (but not all) cases when inner exceptions are returned, it's the innermost exception that has the information that is really useful. It's of course a fairly trivial task to do this in code, but I do it so frequently that I use a small helper method for this: /// <summary>
/// Returns the innermost Exception for an object
/// </summary>
/// <param name="ex"></param>
/// <returns></returns>
public static Exception GetInnerMostException(Exception ex)
{
Exception currentEx = ex;
while (currentEx.InnerException != null)
{
currentEx = currentEx.InnerException;
}
return currentEx;
}
This code just loops through all the inner exceptions (if any) and assigns them to a temporary variable until there are no more inner exceptions. The end result is that you get the innermost exception returned from the original exception.
It's easy to use this code then in a try/catch handler like this (from the example above) to retrieve the more important innermost exception:
object result = null;
string stringResult = null;
try
{
if (parameterList != null)
// use the supplied parameter list
result = helper.ExecuteMethod(methodToCall,target, parameterList.ToArray(),
CallbackMethodParameterType.Json,ref attr);
else
// grab the info out of QueryString Values or POST buffer during parameter parsing
// for optimization
result = helper.ExecuteMethod(methodToCall, target, null,
CallbackMethodParameterType.Json, ref attr);
}
catch (Exception ex)
{
Exception activeException = DebugUtils.GetInnerMostException(ex);
WriteErrorResponse(activeException.Message,
( HttpContext.Current.IsDebuggingEnabled ? ex.StackTrace : null ) );
return;
}
Another function that is useful to me from time to time is one that returns all inner exceptions and the original exception as an array:
/// <summary>
/// Returns an array of the entire exception list in reverse order
/// (innermost to outermost exception)
/// </summary>
/// <param name="ex">The original exception to work off</param>
/// <returns>Array of Exceptions from innermost to outermost</returns>
public static Exception[] GetInnerExceptions(Exception ex)
{
List<Exception> exceptions = new List<Exception>();
exceptions.Add(ex);
Exception currentEx = ex;
while (currentEx.InnerException != null)
{
exceptions.Add(ex);
}
// Reverse the order to the innermost is first
exceptions.Reverse();
return exceptions.ToArray();
}
This function loops through all the InnerExceptions and returns them and then reverses the order of the array returning the innermost exception first. This can be useful in certain error scenarios where exceptions stack and you need to display information from more than one of the exceptions in order to create a useful error message. This is rare but certain database exceptions bury their exception info in mutliple inner exceptions and it's easier to parse through them in an array then to manually walk the exception stack. It's also useful if you need to log errors and want to see the all of the error detail from all exceptions.
None of this is rocket science, but it's useful to have some helpers that make retrieval of the critical exception info trivial.
Resources
DebugUtils.cs utility class in the West Wind Web Toolkit© Rick Strahl, West Wind Technologies, 2005-2011Posted in CSharp .NET