Throw exception but persist stack trace
I want to throw an exception but with custom message and persist stacktrace too. I've gone through various threads.
catch (Exception ex)
{
throw; // Message is read only but stacktrace persist
throw ex; // Message is readonly and strack trace also blows .. worst!
throw new CustomException("My exception");// Message can be overridden but stacktrace lost
throw new CustomException("My message",ex);// same as above. However if this constructor in exception class calls same constructor of base class then .. see below
}
When last apprao开发者_如何学运维ch is used (with custom exception constructor calling base class constructor), output on screen of death is something like:
**The remote server returned an error: (401) Unauthorized.**
[WebException: The remote server returned an error: (401) Unauthorized.]
original stack trace
[NewException: newMessage]
New Stack Trace
Good thing is everything is there on screen. But, on top I want my exception to display i.e. "new message" and not original message.
Hence reconciling my question: HOW can I display on screen of death the original stack trace but with a custom error Message?
throw new CustomException("My message",ex);// same as above (... stacktrace lost)
Your conclusion in the comments is wrong on the last one. The stacktrace is kept in the inner Exception. Standard reporting (including Exception.ToString()
) will report the full stacktrace. This is what you are seeing when you get the constructor right. (Always call the correct base ctor!).
But I don't recognize [WebException]
. In WCF you need
<serviceDebug includeExceptionDetailInFaults="true"/>
I guess your Web environment has a similar feature of suppressing error info towards the client.
Using your fourth approach is how it is generally done and the established pattern. You shouldn't confuse exception handling (or raising) with the way how they are displayed or logged, or whatever.
If you have the output of the (caught) exception under control, i.e. can change/write the respective code, you could simply use the Exception.ToString()
method, which would print the outer exception, including all "inner" ones.
Remark:
Sometimes the inner exceptions are not displayed on purpose by an application. For example in WCF (Windows Communication Foundation) the inner exception is not even transferred from the server to the client unless IncludeExceptionDetails
(via config, code, ...) is set. This usually is done because the inner exception is considered an implementation detail, which may provide an attacker with valuable information to break your application.
What about overriding the StackTrace property?
class CustomException : Exception {
public CustomException(string message, Exception inner) : base(message, inner) {
}
public override string StackTrace {
get {
if (InnerException != null) {
return InnerException.StackTrace;
}
return base.StackTrace;
}
}
}
I agree, option 4 is generally best...
HOWEVER, during development, I find it very useful to put the entire catch clause inside an #if (!DEBUG), with a finally outside it (to allow compilation in Debug mode):
#if (!DEBUG)
catch (Exception ex)
{
// Catch logic for Release mode
}
#endif
finally { }
This makes the API break at the point where the error occurred, instead of at the top level.
Just don't make a habit of #if... in nearly all other cases, use
[Conditional("DEBUG")]
in front of a method instead
精彩评论