You are apparently able to rethrow an Exception without discarding the stack trace in .NET.
However it doesn't appear to be working.
Basic usage I'm following is thus:
[WebMethod]
public void ExceptionTest()
{
try
{
throw new Exception("An Error Happened");
}
catch (Exception ex)
{
evlWebServiceLog.WriteEntry(ex.ToString(), EventLogEntryType.Error);
throw;
}
}
Problem is, the line number in the exception in the line of the throw;
line, not the original throw new
line.
I've tested it in a simple exe project and without the logging to the windows log line. It doesn't make any difference, the stack trace always has the wrong line number in it, making it less than useful.
Why is it doing this? How do I do it correctly?
If a catch block cannot handle the particular exception it has caught, we can rethrow the exception. The rethrow expression causes the originally thrown object to be rethrown.
The java. lang. StackTraceElement. getLineNumber() method returns the line number of the source line containing the execution point represented by this stack trace element.
And always use just "Throw", not "Throw ex". Throw will rethrow the handles exception keeping it's stack intact.
When an exception is caught, we can perform some operations, like logging the error, and then re-throw the exception. Re-throwing an exception means calling the throw statement without an exception object, inside a catch block. It can only be used inside a catch block.
You do not lose original exception if you place it in an inner exception.
[WebMethod]
public void ExceptionTest()
{
try
{
throw new Exception("An Error Happened");
}
catch (Exception ex)
{
evlWebServiceLog.WriteEntry(ex.ToString(), EventLogEntryType.Error);
throw new Exception("Your message", ex);
}
}
I've used the following for years. Don't know if there a less "dodgy" way to achieve it in more up to date .Net frameworks though:
public void PreserveStackTrace(Exception ex)
{
MethodInfo preserve = ex.GetType().GetMethod("InternalPreserveStackTrace",
BindingFlags.Instance | BindingFlags.NonPublic);
preserve.Invoke(ex,null);
}
To use this:
[WebMethod]
public void ExceptionTest()
{
try
{
throw new Exception("An Error Happened");
}
catch (Exception ex)
{
evlWebServiceLog.WriteEntry(ex.ToString(), EventLogEntryType.Error);
PreserveStackTrace(ex);
throw ex;
}
}
Update: based on @dcastro's comment, I'd fancy an extension method in 4.5 (in < 4.5 it could still be an extension wrapping the method above):
public static void ReThrow(this Exception ex)
{
var exInfo = ExceptionDispatchInfo.Capture(ex);
exInfo.Throw();
}
So you'd just have:
catch (Exception ex)
{
evlWebServiceLog.WriteEntry(ex.ToString(), EventLogEntryType.Error);
ex.ReThrow();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With