Best way to check for inner exception?
C#.NetExceptionException HandlingC# 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
.
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