Best way to check for inner exception?

C#.NetExceptionException Handling

C# Problem Overview


I know sometimes innerException is null

So the following might fail:

 repEvent.InnerException = ex.InnerException.Message; 

Is there a quick ternary way to check if innerException is null or not?

C# Solutions


Solution 1 - C#

Great answers so far. On a similar, but different note, sometimes there is more than one level of nested exceptions. If you want to get the root exception that was originally thrown, no matter how deep, you might try this:

public static class ExceptionExtensions
{
    public static Exception GetOriginalException(this Exception ex)
    {
        if (ex.InnerException == null) return ex;

        return ex.InnerException.GetOriginalException();
    }
}

And in use:

repEvent.InnerException = ex.GetOriginalException();

Solution 2 - C#

Is this what you are looking for?

String innerMessage = (ex.InnerException != null) 
                      ? ex.InnerException.Message
                      : "";

Solution 3 - C#

That's funny, I can't find anything wrong with http://msdn.microsoft.com/en-us/library/system.exception.getbaseexception.aspx">Exception.GetBaseException()</a>;?

repEvent.InnerException = ex.GetBaseException().Message;

Solution 4 - C#

The simplest solution is to use a basic conditional expression:

repEvent.InnerException = ex.InnerException == null ? 
    null : ex.InnerException.Message;

Solution 5 - C#

Why so much recursion in these answers?

public static class ExceptionExtensions
{
    public static Exception GetOriginalException(this Exception ex)
    {
        while(ex.InnerException != null)ex = ex.InnerException;
        return ex;
    }
}

Seems like a much more straight forward way to implement this.

Solution 6 - C#

Its an old question but for future readers:

In addition to the answers already posted I think the correct way to do this (when you can have more than one InnerException) is Exception.GetBaseException Method

If you want the exception instance you should do this:

repEvent.InnerException = ex.GetBaseException();

If you are only looking for the message this way:

repEvent.InnerException = ex.GetBaseException().Message;

Solution 7 - C#

With C# 6.0 you can use:

string message = exception.InnerException?.Message ?? "";

This line of code is similar to:

string message = exception.InnerException == null ? "" : exception.InnerException.Message.

https://msdn.microsoft.com/en-us/library/ty67wk28.aspx

http://blogs.msdn.com/b/jerrynixon/archive/2014/02/26/at-last-c-is-getting-sometimes-called-the-safe-navigation-operator.aspx

Solution 8 - C#

With C# 6.0 you can do it in one line.

repEvent.InnerException = ex.InnerException?.Message; 

for other feature of C# 6.0 click here

Solution 9 - C#

Sometimes also InnerException has an InnerException, so you can use a recursive function for it:

public string GetInnerException(Exception ex)
{
     if (ex.InnerException != null)
     {
        return string.Format("{0} > {1} ", ex.InnerException.Message, GetInnerException(ex.InnerException));
     }
   return string.Empty;
}

Solution 10 - C#

With this code, you could be sure that you haven't lost any inner exception messages

catch (Exception exception)
{
   Logger.Error(exception.Message);
   while (exception.InnerException != null)
   {
       exception = exception.InnerException;
       Logger.Error(exception);
   }
}

Solution 11 - C#

Yes:

if (ex.InnerException == null) {
    // then it's null
}

Solution 12 - C#

Here is another possible implementation that appends the messages and stack traces so we get them full:

private static Tuple<string, string> GetFullExceptionMessageAndStackTrace(Exception exception)
{
    if (exception.InnerException == null)
    {
        if (exception.GetType() != typeof(ArgumentException))
        {
            return new Tuple<string, string>(exception.Message, exception.StackTrace);
        }
        string argumentName = ((ArgumentException)exception).ParamName;
        return new Tuple<string, string>(String.Format("{0} With null argument named '{1}'.", exception.Message, argumentName ), exception.StackTrace);
    }
    Tuple<string, string> innerExceptionInfo = GetFullExceptionMessageAndStackTrace(exception.InnerException);
    return new Tuple<string, string>(
    String.Format("{0}{1}{2}", innerExceptionInfo.Item1, Environment.NewLine, exception.Message),
    String.Format("{0}{1}{2}", innerExceptionInfo.Item2, Environment.NewLine, exception.StackTrace));
}


[Fact]
public void RecursiveExtractingOfExceptionInformationOk()
{
    // Arrange
    Exception executionException = null;
    var iExLevelTwo = new NullReferenceException("The test parameter is null");
    var iExLevelOne = new ArgumentException("Some test meesage", "myStringParamName", iExLevelTwo);
    var ex = new Exception("Some higher level message",iExLevelOne);

    // Act 
    var exMsgAndStackTrace = new Tuple<string, string>("none","none");
    try
    {
        exMsgAndStackTrace = GetFullExceptionMessageAndStackTrace(ex);
    }
    catch (Exception exception)
    {
        executionException = exception;
    }
            
    // Assert
    Assert.Null(executionException);

    Assert.True(exMsgAndStackTrace.Item1.Contains("The test parameter is null"));
    Assert.True(exMsgAndStackTrace.Item1.Contains("Some test meesage"));
    Assert.True(exMsgAndStackTrace.Item1.Contains("Some higher level message"));
    Assert.True(exMsgAndStackTrace.Item1.Contains("myStringParamName"));

    Assert.True(!string.IsNullOrEmpty(exMsgAndStackTrace.Item2));

    Console.WriteLine(exMsgAndStackTrace.Item1);
    Console.WriteLine(exMsgAndStackTrace.Item2);
}

Solution 13 - C#

class MyException : Exception
{
    private const string AMP = "\r\nInnerException: ";
    public override string Message
    {
        get
        {
            return this.InnerException != null ? base.Message + AMP + this.InnerException.Message : base.Message;
        }
    }

    public override string StackTrace
    {
        get
        {
            return this.InnerException != null ? base.StackTrace + AMP + this.InnerException.StackTrace : base.StackTrace;
        }
    }
}

Solution 14 - C#

You may simply write like this:

repEvent.InnerException = ex.InnerException?.Message ?? string.Empty;

For get other type of error you may write like this:

string exception = $"\n{nameof(AccountViewModel)}.{nameof(AccountCommand)}. \nMessage: {ex.Message}. \nInnerException:{ex.InnerException}. \nStackTrace: {ex.StackTrace}";

Solution 15 - C#

It is possible to use an exception filter to get more precise aiming.

catch (Exception ex) when (ex.InnerException != null) {...}

Please find more details here

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJL.View Question on Stackoverflow
Solution 1 - C#jristaView Answer on Stackoverflow
Solution 2 - C#Andrew HareView Answer on Stackoverflow
Solution 3 - C#csharptest.netView Answer on Stackoverflow
Solution 4 - C#NoldorinView Answer on Stackoverflow
Solution 5 - C#YaurView Answer on Stackoverflow
Solution 6 - C#DiegoView Answer on Stackoverflow
Solution 7 - C#ToddamsView Answer on Stackoverflow
Solution 8 - C#AshwinView Answer on Stackoverflow
Solution 9 - C#Jan RemundaView Answer on Stackoverflow
Solution 10 - C#kkostView Answer on Stackoverflow
Solution 11 - C#Dan TaoView Answer on Stackoverflow
Solution 12 - C#Ognyan DimitrovView Answer on Stackoverflow
Solution 13 - C#qwert_ukgView Answer on Stackoverflow
Solution 14 - C#agileDevView Answer on Stackoverflow
Solution 15 - C#ValView Answer on Stackoverflow