Question

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?

Was it helpful?

Solution

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);
    }
}

OTHER TIPS

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();
    }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top