Try/Catch Failing Incorrectly - asp.net

I'm trying to use Try/Catch to handle a potential failed connection to a database. There's a Response.Redirect command in the Catch section. Whenever the page loads it redirects as per the Catch section whether the code in the Try section fails or not.
If I comment out the Response.Redirect command in the Catch section the page loads just fine. Similarly, if I replace the Response.Redirect command with code to populate a control on the page with the supposed error being trapped the Try section succeeds. It's something about having Response.Redirect in the Catch section...
Private Sub Page_Load(Sender As Object, e As eventargs) Handles Me.Load
Try
Dim sqlcon As New System.Data.SqlClient.SqlConnection(ConfigurationManager.ConnectionStrings("SarcoidsConnectionString").ConnectionString)
Dim cmd As New System.Data.SqlClient.SqlCommand("SELECT PortalEnabled FROM [tlkSettings]", sqlcon)
sqlcon.Open()
Dim dbReader As System.Data.SqlClient.SqlDataReader = cmd.ExecuteReader()
If dbReader.HasRows Then
While dbReader.Read()
If dbReader("PortalEnabled") = True Then
Response.Redirect("~/SubmitWizard.aspx")
Else
Response.Redirect("~/Maintenance.aspx")
End If
End While
End If
sqlcon.Close()
Catch ex As Exception 'Display Maintenance page if database cannot be connected to
Response.Redirect("~/Maintenance.aspx")
End Try
End Sub

Response.Redirect() without the second parameter of False will generate a ThreadAbortException because .End() is called on the Response object, so the following lines are the issue:
If dbReader("PortalEnabled") = True Then
Response.Redirect("~/SubmitWizard.aspx")
Else
Response.Redirect("~/Maintenance.aspx")
End If
Change it to this:
If dbReader("PortalEnabled") = True Then
Response.Redirect("~/SubmitWizard.aspx", False)
Else
Response.Redirect("~/Maintenance.aspx", False)
End If
The second parameter to Redirect() is the endResponse value, when setting it to False this tells the response to not call .End() and thus does not generate a ThreadAbortException.
Per MSDN documentation:
When you use this method in a page handler to terminate a request for one page and start a new request for another page, set endResponse to false and then call the CompleteRequest method. If you specify true for the endResponse parameter, this method calls the End method for the original request, which throws a ThreadAbortException exception when it completes. This exception has a detrimental effect on Web application performance, which is why passing false for the endResponse parameter is recommended. For more information, see the End method.
Read HttpResponse.Redirect Method documentation for more information.

I think the Problem is related to the other Response.Redirect Statements:
If dbReader("PortalEnabled") = True Then
Response.Redirect("~/SubmitWizard.aspx")
Else
Response.Redirect("~/Maintenance.aspx")
End If
Response.Redirect always throws a ThreadAbortException. This is caught in your exception handler as it catches any exception. Either you substitute the Reponse.Redirect calls or you add a handler the catches ThreadAbortExceptions:
Try
'...
Catch threadAbort As ThreadAbortException
Throw
Catch ex As Exception
'...
End Try
By the way: you should add some Using statements to close the connection and free other objects reliably.

Related

Asp.net Server.GetLastError don't have line number

when i look in the stack trace of a try/catch, i have the row of my code that throw exception.
if i don't manage try/catch to redirect to a custom page and get my last exception with Server.GetLastError i have a different stack trace.
for example:
with try catch i have my line reference
without try catch, on my custom page nothing
i tried also
Dim ex As Exception = Server.GetLastError.GetBaseException
Dim trace As New Diagnostics.StackTrace(ex, True)
as suggested in an other post, but is not working. i wrong something?
this is how i solved:
Dim ex As Exception = Server.GetLastError()
Dim StackTraces As New Diagnostics.StackTrace(ex.InnerException, True)
Dim StackFrame = Nothing
For Each StackFrame In StackTraces.GetFrames()
If (StackFrame.GetFileColumnNumber() > 0) Then
Exit For
End If
Next

Is it okay to catch exception and then cast it to a specific one?

With this code I get the response (error code and message) when an exception from type WebException gets catched.
Dim castExceptionToWebException As WebException = TryCast(ex, WebException)
using r As new StreamReader(castExceptionToWebException.Response.GetResponseStream())
Dim responseContent = r.ReadToEnd()
' DO SOMETHING WITH responseContent
End Using
My questions are: 1.) How could I get the response stream like I did but without casting down to WebException? Is it possible to access it through Exception class 2.) Is there any better work-around?
Replace this with the exceptions you need. Extend the Exception class if you need a custom one.
Try
'do stuff
Dim a = 1 / 0
Catch ex As DivideByZeroException
'handle it
Catch ex As Exception
'bug out
Throw ex
End Try

Thread was being aborted in Response.Redirect

I'm writing a class to validate sessions.
I get the this error
Thread was being aborted
and on researching found that the way around it is to use the false parameter, but using that parameter does not redirect and instead allows the code after the redirect line to execute.
There must be something simple and fundamental here that I'm missing, below is my code.
It breaks in the InvalidAccess() method.
Public Sub New()
CheckSessionCustomerID()
If GotConnectionString() = False Then
InvalidAccess()
End If
End Sub
Public Function GotConnectionString() As Boolean
GotConnectionString = False
Try
If PublicDBConnectionStringName.Trim = String.Empty Then
GotConnectionString = False
Else
PublicConnectionString = System.Configuration.ConfigurationManager.ConnectionStrings(PublicDBConnectionStringName).ToString
If PublicConnectionString.Trim <> String.Empty Then
GotConnectionString = True
End If
End If
Catch ex As Exception
ErrorLogging.LogError(MethodBase.GetCurrentMethod().DeclaringType.Name, MethodInfo.GetCurrentMethod().Name.ToString(), PublicBBTCustomerID & "|" & ex.Message.ToString())
GotConnectionString = False
End Try
End Function
Public Sub CheckSessionCustomerID()
Dim SessionEmployeeID As Integer
Try
If PublicTesting Then
SessionEmployeeID = 1
Else
If IsNothing(HttpContext.Current.Session("EmployeeIDLoggedIn")) Then
InvalidAccess()
ElseIf HttpContext.Current.Session("EmployeeIDLoggedIn").ToString = "0" Then
InvalidAccess()
Else
SessionEmployeeID = Val(HttpContext.Current.Session("EmployeeIDLoggedIn"))
HttpContext.Current.Session("EmployeeIDLoggedIn") = SessionEmployeeID.ToString()
End If
End If
Catch ex As Exception
InvalidAccess()
End Try
End Sub
Private Sub InvalidAccess()
Try
System.Web.HttpContext.Current.Response.Redirect("/InvalidAccess.aspx")
Catch ex As Exception
System.Web.HttpContext.Current.Response.Redirect("/Login.aspx?ID=" & PubliCustomerID & "&ID2=5")
End Try
End Sub
The Thread was being aborted is completely normal when you redirect and wish to stop further execution of request.
In your InvalidAccess method remove Try...Catch block - it is meaningless.
The Response.Redirect will never throw an exception you are interested in.
It is not very clear what have you tried to achieve with this try...catch in your method.
Alternatively, you can use false parameter in Response.Redirect.
You can use the false parameter on the Response.Redirect but then also you have to complete the request to stop execution if that's what you want:
Response.Redirect("/InvalidAccess.aspx", False)
HttpContext.Current.ApplicationInstance.CompleteRequest()
http://www.blakepell.com/asp-net-avoid-threadabortexception-on-response-redirect

Check if code is executing inside Application_Start

Can I check if my exception handler code (registered in Application_Error) is running inside of Application_Start? Tn an ASP.NET app in IIS 7 integrated mode there's RequestContext inside the Application_Start method (see this answer). Right now I'm using a Try ... Catch block to deal with this situation, but if there's a way to check before calling Context.Request it would be nice (Try ... Catch is expensive).
Public Sub Application_Error()
Dim pageName As String
Try
pageName = HttpContext.Current.Request.Path
Catch(ex As Exception)
pageName = "Inside Application_Start, no page name"
End Try
'exception logging co
End Sub

Testing if object Is Nothing results in 'Object required' error

I am supporting some classic ASP pages, one of which uses and re-uses an object conn and disposes of it either when the .asp page finishes processing or right before the page redirects to another page.
<%
dim conn
...
set conn = server.CreateObject("adodb.connection")
...
sub cleanUp()
conn.Close
set conn = nothing
end sub
...
sub pageRedirect(url)
call cleanUp()
response.Redirect url : response.End
end sub
...
' very end of file
call cleanUp()%>
I've found that if there is a redirect, I get a server error right at the line conn.Close, Microsoft VBScript runtime error '800a01a8' Object required. I figure there's no reason why that line would execute more than once but to be safe I rewrote the function
sub cleanUp()
if(not (conn Is Nothing)) then
conn.Close
set conn = Nothing
end if
end sub
But I still get that exact error, now at the line if(not (conn Is Nothing))!! I thought the purpose of Is Nothing was to do a test before using the variable name conn precisely to prevent that 'object required' error, but the test is throwing the same error.
What other test can I use to make sure conn isn't referenced if it'd already been set to Nothing?
is nothing is used to test for an object reference, if the variable does not contain such then the test is invalid & raises an error, so conn can only be tested after its been set to something.
You can;
if isobject(conn) then
if not (conn Is Nothing) then set conn = nothing
end if
Use option explicit (each time a script runs without option explicit, a puppie dies out there), you probably would have detected the problem earlier as Nilpo mentioned.
When you dim a variable that you are going to use as an object reference and test it on Nothing, make it a habbit to set it to Nothing at initialization time(*): dim myObject : Set myObject = Nothing.
(*) Not really at initialization, because the dim's are handled before a routine starts, but when you put all your dim's at the top of a routine, it will practically be the same.
Use the IsNothing function. You should also check that it is an object.
sub cleanUp()
if Not IsNothing(conn) then
if IsObject(conn) then
conn.Close
end if
set conn = nothing
end if
end sub
That being said, I would do it like this since setting a variable to nothing does no harm.
sub cleanUp()
if IsObject(conn) then
conn.Close
end if
set conn = nothing
end sub
More importantly though, your problem is that conn is not in scope for your subroutine. You should probably pass it in as a parameter.

Resources