Why can't I log an error? - asp.net

I have an ASP.NET 2010 app. Basically, anywhere I have reason to suspect an error I employ the following technique in order to attempt to log it.
Try
'Code causing error here
Catch ex As Exception When LogException(ex)
Catch ex As Exception 'Here is where I would put a more specific error
End Try
The LogException function ALWAYS returns false. Therefore, every exception should be caught and logged and then control falls back to the next exception in the block. What really happens is the LogException function is called, but before it can do anything, control goes right back to the next exception in the block above. Why?
Edit...Here is the function that is getting called but returning fter the 1st line...
Public Function LogException(ByVal ex As Exception) As Boolean
Dim oExceptionMgt As New ExceptionMgt 'This line runs
oExceptionMgt.LogException(ex) 'This line should go to db to log error.
Return False
End Function

While I am not a VB programmer if I see a condition such as:
do something when somecondition
That logically says only do something when somecondition is true. Therefore in your example the code is executing correctly because your LogException(Exception ex) method is always false. Which in turn means don't do the something in this instance and continue executing.

Related

How to handle errors inside Catch block

In my application I am getting System.NullReferenceException for my REST call.
This Error is caused by code inside Catch block.
Is it a good idea to put another try catch block inside Catch block?
In the below code following line of code in Catch block is throwing error.
resultObject.ErrorResponse = _client.GetErrorResponse(Of List(Of ErrorResponseObject))(ex, "{""errors"":")
How do I fix this issue, so that user doesn't see any error.
Here is my code.
Public Shared Function POSTCall()
_client = New BaseClient()
Try
strJsonResponse = _client.ExecuteURI(serviceUrl, requestHeader, "POST", resultObject, False, False)
Catch ex As WebException
resultObject.ErrorResponse = _client.GetErrorResponse(Of List(Of ErrorResponseObject))(ex, "{""errors"":") 'This line causing error
If Not IsNothing(resultObject.ErrorResponse) Then
' do some work
End If
Catch Exp As Exception
'Supress the error. Let user goto next step.
Finally
_client = Nothing
End Try
Return resultObject
End Function
You have to catch the error Inside the catch block. This is especially appropriate since what the code is trying to do is to get more info about an error that has already occurrred. Of course, it might be a good idea to log any error occurring, even if the application can continue.
I prefer doing things that are not asynchronous inside the catch. In a case where I need to perform an asynchronous function say rolling back a database transaction, I'll just throw the error and have another asynchronous function handle it in it's catch block in a synchronous way

Is it possible to return from the *calling* method using IL?

There's an annoying quirk in the way Response.Redirect works: you almost always want to terminate excecution right away and jump to the new page:
If ThisIsTheWrongPage Then
Response.Redirect(sUrl, False)
End If
'this code should not execute
DoSomethingWithThisPage
But Response.Redirect doesn't end execution, it just keeps on going and executes the subsequent lines of code. This is causing a lot of havoc in a legacy app I'm maintaining. So you have to do this:
If ThisIsTheWrongPage Then
Response.Redirect(sUrl, False)
Return
End If
What I would like to do is implement a method like this:
Sub RedirectToUrl(sUrl As String)
'redirect to the specified url
HttpContext.Current.Response.Redirect(sUrl, False)
'return from the CALLING method
End Sub
And then I could write this:
If ThisIsTheWrongPage Then
RedirectToUrl(sUrl)
End If
And not have to worry about the missing Return statement. I know it's not hard to write that return statement, but there are about 1,000 of these in the code, and new ones being added, and I want a method that the developer can call and not have to be careful about that Return statement. It's a bug just waiting to happen.
I know there's no way to do this in traditional .NET code, but I was wondering if it could be implemented in IL, to pop the stack twice and jump to the calling method's return location.
This is not possible. You'd be breaking invariants of the calling method. It would be unpredictable what happens when you call a method that you didn't write.
Redirect has a parameter that can be set to make it throw a ThreadAbortException on the current thread. This is made exactly for your use case. It effectively aborts execution of the page.
The only way a method can change the return point of the method that invoked it is to throw an exception. Considering the way many web apps are written with exception handlers to keep pages from returning 500 errors to the user, it could be difficult to provide your desired behavior by throwing an exception.
One problem with instructing a caller to return is there would be no way to specify the return value of that method. Exceptions work around this by propagating the exception itself up the stack until a handler is found.
Have a look at this, it uses the jmp opcode,
maybe this fits your needs.
.assembly JumpTest{}
.module JumpTest.exe
.namespace Test{
.class public auto ansi JumpClass extends [mscorlib]System.Object {
.method public static void Main() cil managed{
.entrypoint
.maxstack 8
ldstr "start"
call void [mscorlib]System.Console::WriteLine(string)
ldstr ""
call void Test.JumpClass::Page(string)
ldstr "end"
call void [mscorlib]System.Console::WriteLine(string)
ret
}
.method public static void Page(string sUrl) cil managed{
ldc.i4.1 //always redirect in this test
brfalse.s target
jmp void Test.JumpClass::RedirectToUrl(string)
target:
ldstr "Page() stuff here"
call void [mscorlib]System.Console::WriteLine(string)
ret
}
.method public static void RedirectToUrl(string sUrl) cil managed{
ldstr "RedirectToUrl() stuff here"
call void [mscorlib]System.Console::WriteLine(string)
ret
}
}}

ASP.NET How to get HttpException ErrorCode

I'm trying to catch and handle a specific HttpException, namely "The remote host closed the connection. The error code is 0x800704CD."
My intention is to add a Catch for the HttpException to the relevant Try block and test for the error code that is generated. Sample code:
Try
// Do some stuff
Catch exHttp As HttpException
If exHttp.ErrorCode.ToString() = "0x800704CD" Then DoSomething()
Catch ex As Exception
// Generic error handling
End Try
But I can't work out how to extract the error code displayed in the exception (i.e. "0x800704CD") from the HttpException object. Converting the integer value of the ErrorCode property to hex returns "800704CD" so clearly I'm not understanding how this code is generated.
Thanks.
Try the Below Code:
Try
// Do some stuff
Catch exHttp As HttpException
If exHttp.ErrorCode = &H800704CD Then DoSomething()
Catch ex As Exception
// Generic error handling
End Try
ErrorCode property is an integer so just test for integer value, no reason to convert to hexadecimal or string.
0x in most programming languages means the following characters denote a hexadecimal number, i.e. 0x800704CD means 800704CD will be interpreted as a hexadecimal number. For VB use &H.
More on VB.Net literals:
http://msdn.microsoft.com/en-us/library/s9cz43ek.aspx
http://msdn.microsoft.com/en-us/library/dzy06xhf.aspx

Is there any difference between ex vs ex.ToString? asp.net

I am talking about Try ... Catch ex as Exception .... End Try
If I pass exception to Error Logger, shall I pass exception object (ex) or ex.ToString ? Would I lose any information by passing ex.ToString?
Basically I was arguing with my manager, that ex.ToString should be excatly the same as passing ex as an object. M I wrong or right ?
One is an exception object, one is the string result of calling ToString on an exception object.
They are different types and have different information.
For logging purposes, there is little difference as the logger would normally call ToString on the exception object anyway.
However, it is better to centralize this - have the exception logger call ToString instead of doing this in every call site to the logger. It is more maintainable and opens you up for doing more things with the exceptions in the future if needed.
An exception object is different from calling .ToString() on the object itself. It depends on how much information you want to capture about the exception itself. If you just want the message, then calling .ToString() will be sufficient since that ends up giving you the message property from the exception object. The MSDN site lists different properties that belong to the base exception class. If you want to log any of these properties, then you will want the exception class and not just the message string.
Also note that different classes that inherit the base exception class provide additional information. As an example, the HttpException class provides additional properties. That information could be useful depending on what you need to see to troubleshoot.
An exception object will contain a lot more information than the result of the .ToString(). At the very least that information will be in a more useful format (ie you can get individual pieces easily).
If all you do in the logger is call exception.ToString() though without using anything else then currently it will be no real difference. However, passing the exception object is probably better for future proofing (ie if you start wanting some more properties of the exception).
For what its worth what ToString does is call the following overload passing true as the parameter:
Private Function ToString(ByVal needFileLineInfo As Boolean) As String
Dim className As String
Dim message As String = Me.Message
If ((message Is Nothing) OrElse (message.Length <= 0)) Then
className = Me.GetClassName
Else
className = (Me.GetClassName & ": " & message)
End If
If (Not Me._innerException Is Nothing) Then
className = String.Concat(New String() { className, " ---> ", Me._innerException.ToString(needFileLineInfo), Environment.NewLine, " ", Environment.GetRuntimeResourceString("Exception_EndOfInnerExceptionStack") })
End If
Dim stackTrace As String = Me.GetStackTrace(needFileLineInfo)
If (Not stackTrace Is Nothing) Then
className = (className & Environment.NewLine & stackTrace)
End If
Return className
End Function
As you can see it basically will output the class, message, innerexception.ToString() and stack trace.
Exception object is different than .ToString(). It has vast variety of properties, also if you need to pass the message only, you can use Ex.Message;

Missing StackTrace Information

I seem to be missing some information from my stack trace, here is what i'm getting:
at Foo.Bar(DataTable table) in D:\Foo\Bar\authoring\App_Code\FooBar.vb:line 87
Where is the rest of the stack trace infomation?
EDIT:
Custom errors in the Web.Config is set to off, i'm handling the error where it's caught like this:
Catch ex As Exception
Respose.Write(ex.StackTrace)
End Try
The Stack Trace is still getting truncated.
Make sure customErrors is set to "RemoteOnly" or "Off" in your web.config to disable friendly errors.
Or possibly stack trace getting reset? (Although if this was the case you still should see something)
Will reset your stack trace.
catch(Exception ex)
{
throw ex;
}
Will NOT reset your stack trace.
catch(Exception ex)
{
throw;
}
EDIT:
ex.StackTrace gets the current stack. The stacktrace starts
where the exception was thrown(error happens) and ends at the current stack frame where the exception is caught. So it is reversing the call stack. Since you are writing out stacktrace as soon as it happens it doesn't get a chance to go any further up the callstack.
Depending on what you are doing you can try a few things.
//To just see the stackTrace
Catch ex As Exception
Throw
End Try
Environment.StackTrace - Gets current stack trace information
//If you are trying to log the stacktrace
Catch ex As Exception
Respose.Write(Environment.StackTrace)
Respose.Write(ex.StackTrace)
End Try
//If is hiding then try - hiding as in throw ex vs just throw
Catch ex As Exception
//careful innerException can be null
//so need to check before using it
Respose.Write(ex.InnerException)
End Try
One of those methods should work for you.

Resources