Below, why doesn't Throw maintain my originating line number?
If I run the DerivedPage, my log file lists the error as line 7.
Shouldn't it say line 4? It would make sense if I had Throw ex, but I don't.
Isn't Throw by itself just supposed to rethrow and bubble up the error?
If I remove the Try...Catch block entirely in DerivedPage, then my log file correctly lists 3 as the error line, but I am not able to log any info in case of an error.
What can I do to maintain my DerivedPage, and still have my log keep the correct line number?
Public Class DerivedPage Inherits BasePage
Page_Load(o,e)
Try
Dim a = 3 -"a"
Catch ex As Exception
log.Info(...)
Throw
End Try
End Class
base page:
Public Class BasePage
Protected Overrides Sub OnError(e)
MyBase.OnError(e)
log.Error(Me.GetType(), Server.GetLastError)
End Sub
End Class
EDIT: log.Error does output the InnerException if it exists. It does in this case. However, the stack trace for the InnerException doesn't contain a line number, just the Exception details.
When an exception is rethrown, the original exception details are stored in the InnerException property of the object. You should have all of your details there.
There is a method that you can implement that will give you the correct line number in your stack trace:
Rethrowing exceptions and preserving the full call stack trace - Fabrice's weblog
The code is in C#, but the code for the PreserveStackTrace method should be relatively easy to port over to VB.NET.
SOLUTION: Two solutions per Wrong line number on stack trace are throw a new exception with the current exception as the inner, or use a helper method.
I'm going to go with throwing a new exception.
Related
This is what I get when I use Exception.Message :
System.Web.Services.Protocols.SoapException: The server can not process the request. ---> System.NullReferenceException: Object reference not set to an instance of an object in . in WebService.ProcessRequestArc... --- End of inner exception stack trace ---
Is it possible to configure a web application so that exceptions only send the part in bold in my example?
Or do you know of any way to extract only that part?
The Message property of an exception does not follow any pattern. In particular, the Message property will be different depending on the current culture settings (language).
But even if you are only concerned about a single language, you should never depend on anything in the Message property. It simply contains whatever the developer who threw the exception thinks you might want to see.
In particular, it does not contain anything that you should display to your users!
I didn't quite understand your problem at first. To avoid seeing the Stack Trace, you simply had have display Server.GetLastError().Message. On further examination I see that your problem is that exceptions are getting wrapped into a HttpException, and the Message from HttpException concatenates the method info with the original exception message.
Solution
In web.config you need to add a custom error section.
<customErrors defaultRedirect="Error.aspx"
mode="On" redirectMode="ResponseRewrite">
In Error.aspx you can do the following to check if it's an HttpException, and if so get the inner exception's message.
var ex = Server.GetLastError();
string message;
if (ex != null)
{
message = ((ex is HttpException || ex is SoapException) && ex.InnerException != null)
? ex.InnerException.Message : ex.Message;
}
else
{
message = "An error has occurred.";
}
Response.Write(message);
On your page you just want to show Server.GetLastError().Message.
Here is the before and after for a divide by zero error:
Before: Default.aspx(4): error CS0020: Division by constant zero
After: Attempted to divide by zero.
For SoapException to actually have the InnerException property not be null, then you need to throw a SoapException with the actual exception inside.
Here are some links from MSDN regarding the customErrors section and error handling:
customErrors Element
Complete Example for Error Handlers
I'm trying to debug a third party library that is throwing an null reference exception in certain cases, but I am only getting the exception from the javascript side, which doesn't contain the stack trace in the error message.
Is there a value in the scriptmanager or something similar with more information about the exception, or should I be removing the update panels to get at the raw exception?
(Easier said then done, its nested several update panels deep)
Thanks!
Look into ScriptManager.AsyncPostBackError event.
You can do something like this
protected void ScriptManager1_AsyncPostBackError(object sender, AsyncPostBackErrorEventArgs e)
{
//do something with the exception
log(e.Exception.Message);
// show a message to the user.
ScriptManager1.AsyncPostBackErrorMessage =
"An error occurred." + e.Exception.Message;
}
}
You can turn off ajax features temporary by setting EnablePartialRendering property of the ScriptManager to false.
I have a global error trap in the Application_Error method of Global.asax that writes any unhandled exception to a log file.
Is there anyway of reporting the variable names and their values as part of the exception report?
Unless you do something really tricky with Aspect-Oriented Programming, you pretty much need to make sure that you manually introduce any relevant information into the stack trace when exceptions are thrown. For example:
public void DoSomething(int number, string name)
{
try
{
...
}
catch (Exception e)
{
throw new Exception("Error occurred while doing something: " +
new {number, name}, e);
}
}
This way, the number and name will be included in the stack trace when this exception trickles up to the top level.
Edit
After reading David Stratton's answer, I felt the need to expand on this a little. I get the sense that even some very experienced C# programmers haven't learned some of the tricks that I've learned.
First of all, I wanted to point out that the exception-handling system in .NET was designed with the idea of an InnerException specifically for this purpose (providing additional information at various points of the stack trace), and it is not at all hacky to do. However, you should definitely provide the exception as the innerException constructor parameter, rather than appending e.ToString() to the new exception's message.
Secondly, based on various comments and answers I've read on StackOverflow, as well as my own experience, it's best to:
Avoid catching an exception if there's nothing specific you plan to do with it.
When you catch an exception, rethrow it unless you know why the exception was thrown and you're in a scope where you know how to gracefully retreat from what you were trying to do. Simply pretending nothing went wrong is asking for more trouble down the road.
When re-throwing exceptions, either just throw; to preserve the original exception's stack trace, or include the original exception as a new exception's InnerException.
Consistently log exceptions that don't get re-thrown. This will generally only happen at the UI level, so you can tell the user something unexpected happened rather than allowing the program to crash.
Finally, I wanted to mention that the anonymous type declaration syntax is ideal for this kind of thing because it is very concise and it will automatically produce a string that uses the given variable names and values. For example, new {number, name}.ToString() might produce "{ number = 1, name = Test }".
We do this in some cases, but in a roundabout way. We use a try/catch at the granular level and if we want to pass the exception up to the global error handler, we build the error message. For example:
int someCounterValue = 0;
string someStringValue = "Some string we want to track to send to the global error handler."
private void SomeFunction()
{
try
{
someStringValue = "in the try block";
someCounterValue = 1.5 // should thrown an exception
}
catch(Exception ex)
{
throw new Exception("Error in SomeFunction. someStringValue = " + someStringValue + "; someCounterValue = " + someCounterValue.ToString() + "\r\nException details: " + ex.ToString());
}
}
It's a lot of work so we really don't do this very often. Usually our error handling is better handled at the local level but in those very rate cases where you want to pass it off to the global error handler, this is about the only way we've found, since the variables would be out of scope otherwise, and therefore, inaccessible.
An easier/less hack-like option would be to set up a static class in your web app called ErrorLogger or something similar, and just handle the exceptions better locally and pass them up to the global handler ONLY when you can't do it locally.
In my opinion (and in the way we do it here by policy) a global error handler should be used to catch exceptions that you forgot to handler better at a more granular level. It should NOT just be an easy way to be lazy about proper exception handling.
Also it feels like a hack to me, so if anyone has a better option I'd like to know it, too.
When I get an Object Ref error, it can sometimes be a real pain to find out which variable is causing the error (when you can't debug). Is there a way for this error to throw the classname that isn't assigned?
So: I want the name of the type of the variable that was unexpectedly null.
Thanks in advance.
I dont think you can get the class name, the closes I get is to get the class and method name, then the stack trace:
try
{
}
catch ( Exception ex )
{
xxx.API.ErrorHandler.Handler.HandleError( ex, System.Reflection.MethodBase.GetCurrentMethod().Name, System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName );
}
Well, its only the information in the stack trace which would be the first step in finding out where the error has originated. Also you should make sure you check the complete stack trace (all inner exceptions too). This would give you the method name with complete namespace. So that should be fairly good step to see where the error is, unless the standard coding is really bad.
How to identify the line nr. where the exception has occured and show a piece of code around the exception?
I would like to implement a custom exception handler page which would display the stack trace, and I'm looking for the easiest way to accomplish the above. While most of the information is available through the Exception object, the source code information is not available there.
You need to use the StackTrace class.
For example:
var st = new StackTrace(exception, true);
var sourceFrame = Enumerable.Range(0, st.FrameCount).FirstOrDefault(i => st.GetFrame(i).GetFileLineNumber() > 0);
This code will find the first frame which has line number information available, or null, if none of the frames have line numbers.
You can then call the methods of the StackFrame object to get more information. Note that source information is usually only available in debug builds.