What's wring with this try-catch block?

  • Thread starter Thread starter HillBilly
  • Start date Start date
H

HillBilly

This is freaking me out. I'm using Membership and trying to determine if the
database is online. The GetConnectionString( ) method returns a connection
string as expected but not when used in the try block.

I have the Open() and Close() methods commented out while using the
Response.Redirect to test.
The code in the try block as shown will --never execute-- but the code in
the catch block --always executes-- whether the database is online or not.

WTF???

protected void LoginButton_Click(object sender, EventArgs e)
{
// Redirect proves this test works
//Response.Redirect(ResolveUrl("~/homepage.aspx?LoginButton_Click"));

SqlConnection testConnection = new
SqlConnection(GetConnectionString("MyConnectionString"));
if (!String.IsNullOrEmpty(testConnection.ToString()))
{
try
{
//testConnection.Open();
//testConnection.Close();
Response.Redirect(ResolveUrl("~/homepage.aspx?MyConnectionString-Found"));
}
catch (Exception ex)
{
Response.Redirect(ResolveUrl("~/homepage.aspx?LoginButton_Click-Caught-Exception"));
}
}
}
 
Why not simple set a breakpoint behind this part of code and see what it is?

testConnection.ToString())
 
This is freaking me out. I'm using Membership and trying to determine if the
database is online. The GetConnectionString( ) method returns a connection
string as expected but not when used in the try block.

I have the Open() and Close() methods commented out while using the
Response.Redirect to test.
The code in the try block as shown will --never execute-- but the code in
the catch block --always executes-- whether the database is online or not..

WTF???

protected void LoginButton_Click(object sender, EventArgs e)
{
    // Redirect proves this test works
    //Response.Redirect(ResolveUrl("~/homepage.aspx?LoginButton_Click"));

    SqlConnection testConnection = new
SqlConnection(GetConnectionString("MyConnectionString"));
    if (!String.IsNullOrEmpty(testConnection.ToString()))
    {
        try
        {
            //testConnection.Open();
            //testConnection.Close();
            Response.Redirect(ResolveUrl("~/homepage.aspx?MyConnectionString-Found"));
        }
        catch (Exception ex)
        {
            Response.Redirect(ResolveUrl("~/homepage.aspx?LoginButton_Click-Caught-Exce­ption"));
        }
    }



}- Hide quoted text -

- Show quoted text -

Right before your if statement have the app throw a messagebox with
the contents of the string:
MessageBox.Show(testConnection.ToString());
 
I can set breakpoints all over the place --except-- on the try statement. I
don't see anything unusual --except-- an the Error List states: The variable
'ex' is declared but never used noting if I change (Exception ex) to
(Exception e) I get a different error about the variable already being used
in the same scope.

I set breakpoints and I can read the Call Stack and the Locals window. I
really don't know what to look for that indicates why the code in the try
block will not execute. I can only assume the stupid error about ex which
makes no sense to me may be the problem.

I can see the connection string and know its valid and functional. It may
not be a best practice but I don't know any other way to determine when the
database may be offline so I'm trying to force an exception I could easily
catch if and when the database may be offline by using the
testConnection.Open() method which will open and close if the database is
online but should be caught by the catch block when offline.

This is so strange to me not even this code will allow the redirect in the
try block to execute. The click event keeps executing the code in the catch
LoginButton_Click-Caught-Exception...

protected void LoginButton_Click(object sender, EventArgs e)
{
// Redirect proves this test works
//Response.Redirect(ResolveUrl("~/homepage.aspx?LoginButton_Clicked"));

if( 1 == 1 )
{
try
{
Response.Redirect(ResolveUrl("~/homepage.aspx?LoginButton_Click-Try-Block"));

}
catch (Exception ex)
{
Response.Redirect(ResolveUrl("~/homepage.aspx?LoginButton_Click-Caught-Exception"));
}
}

}


This is freaking me out. I'm using Membership and trying to determine if
the
database is online. The GetConnectionString( ) method returns a connection
string as expected but not when used in the try block.

I have the Open() and Close() methods commented out while using the
Response.Redirect to test.
The code in the try block as shown will --never execute-- but the code in
the catch block --always executes-- whether the database is online or not.

WTF???

protected void LoginButton_Click(object sender, EventArgs e)
{
// Redirect proves this test works
//Response.Redirect(ResolveUrl("~/homepage.aspx?LoginButton_Click"));

SqlConnection testConnection = new
SqlConnection(GetConnectionString("MyConnectionString"));
if (!String.IsNullOrEmpty(testConnection.ToString()))
{
try
{
//testConnection.Open();
//testConnection.Close();
Response.Redirect(ResolveUrl("~/homepage.aspx?MyConnectionString-Found"));
}
catch (Exception ex)
{
Response.Redirect(ResolveUrl("~/homepage.aspx?LoginButton_Click-Caught-Exce­ption"));
}
}



}- Hide quoted text -

- Show quoted text -

Right before your if statement have the app throw a messagebox with
the contents of the string:
MessageBox.Show(testConnection.ToString());
 
HillBilly said:
This is so strange to me not even this code will allow the redirect in the
try block to execute. The click event keeps executing the code in the catch
LoginButton_Click-Caught-Exception...

protected void LoginButton_Click(object sender, EventArgs e)
{
// Redirect proves this test works
//Response.Redirect(ResolveUrl("~/homepage.aspx?LoginButton_Clicked"));

if( 1 == 1 )
{
try
{
Response.Redirect(ResolveUrl("~/homepage.aspx?LoginButton_Click-Try-Block"));

}
catch (Exception ex)
{
Response.Redirect(ResolveUrl("~/homepage.aspx?LoginButton_Click-Caught-Exception"));
}
}
}

Response.Redirect works by setting something and then throwing an
exception (by default). If you look at the exception which is being
thrown, I susect you'll find it's a ThreadAbortException. Look at the
documentation for Response.Redirect for more information.
 
Response.Redirect works by setting something and then throwing an
exception (by default). If you look at the exception which is being
thrown, I susect you'll find it's a ThreadAbortException. Look at the
documentation for Response.Redirect for more information.

--
Jon Skeet - <[email protected]>
Web site: http://www.pobox.com/~skeet
Blog: http://www.msmvps.com/jon.skeet
C# in Depth: http://csharpindepth.com

Aha! I'll certainly study that thank you but still, what do you do to
determine if the database is offline? I thought I'd convert the code into a
method called before logging in or any other attempt to access the database.
But if its not even online then what?
 
breitak67 said:
I'd have to look this up - I know a Server.Redirect that occurs within
the try of a try..catch block throws a thread termination exception.
Perhaps Response.Redirect does as well. To fix it, just use
Response.Redirect(url,false) instead, or you can throw an extra chunk
between your try and catch blocks:

catch (System.Threading.ThreadAbortException ex)
{//Do nothing }

Thank you, that's correct as I'm learning. How would you determine if the
database is offline or not?
 
HillBilly said:
Aha! I'll certainly study that thank you but still, what do you do to
determine if the database is offline? I thought I'd convert the code into a
method called before logging in or any other attempt to access the database.
But if its not even online then what?

Trying to connect (and executing some basic operation) seems reasonable
to me - but unconnected to the problem you're seeing. I suggest you
extract the desired functionality (basically an "online/offline"
boolean check) into a separate method - that way you'll be catching
just the database exception there, rather than both the database
exception *and* the exception from the redirect.
 
Jon Skeet said:
Trying to connect (and executing some basic operation) seems reasonable
to me - but unconnected to the problem you're seeing. I suggest you
extract the desired functionality (basically an "online/offline"
boolean check) into a separate method - that way you'll be catching
just the database exception there, rather than both the database
exception *and* the exception from the redirect.

--
Jon Skeet - <[email protected]>
Web site: http://www.pobox.com/~skeet
Blog: http://www.msmvps.com/jon.skeet
C# in Depth: http://csharpindepth.com

I refactored as this implementation...

#region Method: IsDatabaseOffline()...
public void IsDatabaseOffline()
{
SqlConnection connection = new
SqlConnection(GetConnectionString("MyConnectionString"));
if (!String.IsNullOrEmpty(connection.ToString()))
{
try
{
connection.Open();
connection.Close();
connection.Dispose();
}
catch (SqlException ex)
{
Response.Redirect(ResolveUrl("~/ErrorPages/DatabaseError.aspx?Caught-SqlException"));
}
}
}
#endregion

You know I didn't even need the redirect in the try block but it sure taught
me a lesson in two ways. First, I've learned about ThreadAbortException and
secondly I realized when the IsDatabaseOffline method is marked static it
causes an error because the SqlConnection object is not static which implies
all members of a static method must themselves be static.

More work to write the log and notification code but this should be muy
bueno for now eh?
 
HillBilly said:
I refactored as this implementation...

#region Method: IsDatabaseOffline()...
public void IsDatabaseOffline()
{
SqlConnection connection = new
SqlConnection(GetConnectionString("MyConnectionString"));
if (!String.IsNullOrEmpty(connection.ToString()))
{
try
{
connection.Open();
connection.Close();
connection.Dispose();
}
catch (SqlException ex)
{
Response.Redirect(ResolveUrl("~/ErrorPages/DatabaseError.aspx?Caught-SqlException"));
}
}
}
#endregion

No, that is still a bad thing in my view, for a few reasons:

1) You're mixing your database logic with your page logic. What if you
ever want to create a page with diagnostics of various things? Or use
this code for something other than a web page?

2) A method called "IsDatabaseOffline" really should return something.
Based on the method name I *certainly* wouldn't expect it to be
redirecting a response.

3) You should still use a "using" statement for the connection, IMO.
That way you don't need to explicitly close it or call Dispose (doing
both is reasonably pointless, btw) but you'll still close it if
something odd (like an asynchronous exception) happens after Open.

4) It may well be worth actually *doing* something with the connection
- something which forces it to try to talk to the database for real.
Otherwise you may find you've got stale connections which can be opened
and closed with no problems, but can't do any real work. I know that's
a problem with some connections on some platforms, but I don't know if
it's relevant in your particular situation.
You know I didn't even need the redirect in the try block but it sure taught
me a lesson in two ways. First, I've learned about ThreadAbortException and
secondly I realized when the IsDatabaseOffline method is marked static it
causes an error because the SqlConnection object is not static which implies
all members of a static method must themselves be static.

The SqlConnection object is declared inside the method - it's
irrelevent. However, the Response property isn't static, and
GetConnectionString may not be depending on what you're doing.
 
Jon Skeet said:
No, that is still a bad thing in my view, for a few reasons:

1) You're mixing your database logic with your page logic. What if you
ever want to create a page with diagnostics of various things? Or use
this code for something other than a web page?

2) A method called "IsDatabaseOffline" really should return something.
Based on the method name I *certainly* wouldn't expect it to be
redirecting a response.

3) You should still use a "using" statement for the connection, IMO.
That way you don't need to explicitly close it or call Dispose (doing
both is reasonably pointless, btw) but you'll still close it if
something odd (like an asynchronous exception) happens after Open.

4) It may well be worth actually *doing* something with the connection
- something which forces it to try to talk to the database for real.
Otherwise you may find you've got stale connections which can be opened
and closed with no problems, but can't do any real work. I know that's
a problem with some connections on some platforms, but I don't know if
it's relevant in your particular situation.


The SqlConnection object is declared inside the method - it's
irrelevent. However, the Response property isn't static, and
GetConnectionString may not be depending on what you're doing.

--
Jon Skeet - <[email protected]>
Web site: http://www.pobox.com/~skeet
Blog: http://www.msmvps.com/jon.skeet
C# in Depth: http://csharpindepth.com

So when all is said and done I should not try to write superfluous code
worrying about the database being offline as that circumstance should and
would be caught with a SqlException anyway? And how is the exception cuaght
when using the 2.0 Login controls without rewriting authentication?
 
So when all is said and done I should not try to write superfluous code
worrying about the database being offline as that circumstance should and
would be caught with a SqlException anyway?

Well, that's one option. But my point was mostly to separate out the
test for whether or not the database is online from what you happen to
want to do at the moment when the database is offline.

Write a simple method which tests for database connectivity and returns
the status (for the moment a simple bool would do) - and then act on
that return value. That's a much more flexible approach.
And how is the exception cuaght
when using the 2.0 Login controls without rewriting authentication?

No idea, I'm afraid. I'd ask on an ASP.NET group. Be aware that the
database could go offline after you do your check though, of course.
 
Jon Skeet said:
Well, that's one option. But my point was mostly to separate out the
test for whether or not the database is online from what you happen to
want to do at the moment when the database is offline.

Write a simple method which tests for database connectivity and returns
the status (for the moment a simple bool would do) - and then act on
that return value. That's a much more flexible approach.


No idea, I'm afraid. I'd ask on an ASP.NET group. Be aware that the
database could go offline after you do your check though, of course.

--
Jon Skeet - <[email protected]>
Web site: http://www.pobox.com/~skeet
Blog: http://www.msmvps.com/jon.skeet
C# in Depth: http://csharpindepth.com

Offline --after-- logging in? Gees that's a stunning thought ;-) so please,
one more comment if you would as I appreciate your attention. I thought --I
was writing a simple method-- which tests for database connectivity? I'm
asking myself how much simpler could it get than to start with the
connection which either is or isn't active and hence would fail and easily
be caught. The impetus to put it into a method I was thinking makes it
possible for reuse everywhere there is an initial request to access and use
the database as you said it yourself, "what happens when the database goes
offline afterwards?" And that can't be prevented by the web developer nor
caught in any way I can imagine.

Its not like I haven't studied the context of this issue looking all over
the place and there doesn't seem to be much of anything anywhere other than
our colleagues blogging or documenting SqlExceptions in general.

I'm going the route of writing more code. I mean what the hell. I'll only
learn yet more along the way. But you know what they say eh? All developers
are lazy so I just wanted to be like everybody else. :-)
 
HillBilly said:
Offline --after-- logging in?

That's one possibility. Another is that it goes offline *after* you've
tested connectivity, but *before* you've actually done the login.
Basically I'm saying that any test you do is stale immediately after
you've done it. That's not to say it's not worth doing, but just bear
the possibility in mind :)
so please, one more comment if you would as I appreciate your
attention. I thought --I was writing a simple method-- which tests
for database connectivity? I'm asking myself how much simpler could
it get than to start with the connection which either is or isn't
active and hence would fail and easily be caught.

Sounds reasonable to me.
The impetus to put it into a method I was thinking makes it possible
for reuse everywhere there is an initial request to access and use
the database as you said it yourself, "what happens when the database
goes offline afterwards?" And that can't be prevented by the web
developer nor caught in any way I can imagine.

Indeed. There's really not a lot you can do about it, other than be
aware of the remote possibility, and deal with it *reasonably*
gracefully (in particular, don't try to log the error to the
database!).
 
Back
Top