Getting all messages from InnerException(s)?

Solution 1:

Unfortunately LINQ doesn't offer methods that could process hierarchical structures, only collections.

I actually have some extension methods that could help do this. I don't have the exact code in hand but they're something like this:

// all error checking left out for brevity

// a.k.a., linked list style enumerator
public static IEnumerable<TSource> FromHierarchy<TSource>(
    this TSource source,
    Func<TSource, TSource> nextItem,
    Func<TSource, bool> canContinue)
{
    for (var current = source; canContinue(current); current = nextItem(current))
    {
        yield return current;
    }
}

public static IEnumerable<TSource> FromHierarchy<TSource>(
    this TSource source,
    Func<TSource, TSource> nextItem)
    where TSource : class
{
    return FromHierarchy(source, nextItem, s => s != null);
}

Then in this case you could do this to enumerate through the exceptions:

public static string GetaAllMessages(this Exception exception)
{
    var messages = exception.FromHierarchy(ex => ex.InnerException)
        .Select(ex => ex.Message);
    return String.Join(Environment.NewLine, messages);
}

Solution 2:

You mean something like this?

public static class Extensions
{
    public static IEnumerable<Exception> GetInnerExceptions(this Exception ex)
    {
        if (ex == null)
        {
            throw new ArgumentNullException("ex");
        }

        var innerException = ex;
        do
        {
            yield return innerException;
            innerException = innerException.InnerException;
        }
        while (innerException != null);
    }
}

This way you could LINQ over your entire exceptions hierarchy, like this:

exception.GetInnerExceptions().Where(e => e.Message == "Oops!");

Solution 3:

How about this code:

private static string GetExceptionMessages(this Exception e, string msgs = "")
{
  if (e == null) return string.Empty;
  if (msgs == "") msgs = e.Message;
  if (e.InnerException != null)
    msgs += "\r\nInnerException: " + GetExceptionMessages(e.InnerException);
  return msgs;
}

Usage:

Console.WriteLine(e.GetExceptionMessages())

Example of output:

There was no endpoint listening at http://nnn.mmm.kkk.ppp:8000/routingservice/router that could accept the message. This is often caused by an incorrect address or SOAP action. See InnerException, if present, for more details.

InnerException: Unable to connect to the remote server

InnerException: No connection could be made because the target machine actively refused it 127.0.0.1:8000

Solution 4:

For those, who are waiting for a one-liner.

exc.ToString();

This will go through all your inner exceptions and return all messages, the downside is that it will also contain stack traces, etc.