Why Does Asp.Net Use The Innermost Exception?

G

Guest

First let me say that I understand that Asp.Net wraps my exception in an
HttpUnhandledException. I have found a lot of discussion about that on the
web, which was informative, but not helpful. Let me explain how my question
is different.

Second, let me say that I have two questions. One is an ASP.Net related
question. The other is a general System.Exception question. They are related
but also individual.

Okay here is my problem...

I have an ADO wrapper library. I use it to wrap provider-specific exceptions
with my own. For example when a opening a connection fails, my library has
its own exception that it throws. Consumers of my library don't know if it
was an Oracle connection that failed, an SqlClient connection that failed,
etc. However just in case, I do put the original ADO provider's exception in
the *innerException* property of my library's exception.

When an exception is thrown by my library, and not handled in the aspx page,
IIS displays the default error screen, which is fine. But it displays the
*inner-most* exception. So in this case, instead of displaying my library's
exception, it displays the provider's exception, which I had put into my
library's exception's innerException property. This is not what I want. I
don't want consumers of my library to see the provider exception unless they
really want to.

Like I said at the top of my post, I understand that it would not display
the outer-most exception. That would be the HttpUnhandledException. But I
don't understand why it drills down to the inner-most exception.

So I started poking around...

I stopped populating my library's exception's innerException. Now IIS
displayed my exception just like I wanted. When there is no innerException,
IIS displays my exception.

I wondered if there was something special about the provider exception that
made IIS want to display it, instead of displaying mine. So I populated my
library's exception's innerException with a new dummy exception. IIS still
displayed the inner-most exception.

Feeling frustrated I wondered if GetBaseException was being called. So I
overrode it. *Success!* If I return a new dummy exception from my library's
overridden GetBaseException method, that is what shows up in IIS. So clearly,
yes, IIS is showing the inner-most exception.

Why does IIS take it upon itself to decide that the inner-most exception
should be displayed? This makes me mad. Why would I wrap one exception inside
another if I don't want the outer exception to be exposed to the world? I
fully understand that IIS does not want to display the outer-most exception
(the httpUnhandledException).

Thinking, I override GetBaseException to return "me" (c# syntax "this"). It
doesn't work. I'm not sure what is going on. When I am not sure what is going
on I always turn to my trust friend the .Net Reflector!
(http://www.aisto.com/roeder/dotnet/). Sure enough take a look at this little
method known as System.Exception.GetBaseException()...

Public Overridable Function GetBaseException() As Exception
Dim exception1 As Exception = Me.InnerException
Dim exception2 As Exception = Me
Do While (Not exception1 Is Nothing)
exception2 = exception1
exception1 = exception1.InnerException
Loop
Return exception2
End Function

Notice anything funny? It does *not* call the innerExceptions's
GetBaseException. It just starts drilling down on *it's own* through the
InnerExceptions directly. Why doesn't it call the InnerException's
GetBaseException? That wouldn't be recursion exactly, but it would make more
sense to me. As it stands, overriding GetBaseException only works when you
are the outer-most exception. If the overriding exception gets wrapped up as
an inner exception (say for example in an HttpUnhandledException, as in this
case) all your precious overridden GetBaseException logic is *out the window*.

So I have two questions...

1) Why does IIS display the GetBaseException of the HttpUnhandledException
instead of the InnerException?

2) Why does System.Exception.GetBaseException drill down on its own through
the InnerExceptions, instead of honoring the possibly overridden
GetBaseExceptions?

Any information, education, guidance, or I-feel-your-pains would be greatly
appreciated.

John DeHope
 
K

Karl Seguin [MVP]

I'll answer #1...

ASP.NET displays exceptions to help you debug. You are supposed to set
customError="On" or "RemoteOnly" meaning they should only ever been
"exposed" to developers. As you know, when it comes to troubleshooting an
error, the inner exception always contains the most meaningful information.
In other words, I think the reason ASP.NET displays the inner-most exception
is because it's not only the most useful, but also because it should only
been seen by someone actually trying to solve the error.

A lot more people would complain if it _didn't_ display the inner exception.

I know very little about what exactly you're doing, so I won't pass
judgement too quickly, but do consider this .NET design guideline:
"Do not create and throw new exceptions just to have 'your team's'
exception."
from http://blogs.msdn.com/kcwalina/archive/2005/03/16/396787.aspx


As for GetBaseException questions, personally, I'd think this is by-design
(ie, they always want the root exception to be returned). But why make it
overridable?!

Well, looking at the docs sheds some light on the issue:

First, it's clear that the design of this is very strict:
"The first exception thrown in a chain of exceptions", and
"For all exceptions in a chain of exceptions, the GetBaseException method
must return the same object (the base exception)."

So it looks like a pretty well-defined design..but why the overridable,
well:
"Notes to Inheritors The GetBaseException method is overridden in classes
that require control over the exception content or format."

in other words, it doesn't look like GetBaseException is there to change the
core behaviour (returning the root exception) but rather the
content/format....


Karl
 
G

Guest

Thanks Karl, that information was very helpful. I mised the docs you
referenced. Normally I just read the code docs that you get from an F1 help
search. Are those you quoted from someplace else?

I'm no best practices guru. I just find the exception messages to sometimes
be infuriatingly obscure. And also, when wrapping up multiple ADO providers
into a single simpler api, I don't want to see the provider's error messages
unless I *really* need them. It's not helpful in my mind to have a wrapper to
eliminate the need to know your ado provider, just to have to know your ado
provider when an exception is thrown. Does that sound like a "my team's
exceptions" situation?

A recent example will help illustrate my point. I had a connection string
pointing to the wrong database server. It just so happens that the server
existsed and was running fine, but did not have a DB by the name I had
mentioned in my conn string. So I did not get an exception for the server
being not-there or unavailable, but I did get one for the database I wanted
not being there. Unfortunately the sql server 2000 exception I got didn't say
"no such database 'X'" it said "unable to connect to database 'X'. Logon
fails for user 'Y'". Is it me or does that sound like a permissions problem,
and not a no-such-database problem? Okay that's a rhetorical question. My
real point to telling this story is to illustrate the kind of (in my mind)
problem with keeping up with individual ado provider's exception messages. My
ado wrapper library now has a custom "database not found" exception that is
thrown whenever such a thing happens, leading to no confusion. Is that a
legitimate usage of exception wrapping? Or is that a "my team's exception"?
 
K

Karl Seguin [MVP]

Well, the entire when to write your own exceptions and when not to is
confusing to me too :) I've seen what are clear abuses in my mind, which I
think is what the guidelines are warning against. I can certainly see the
need to abstract away a provider-type model away from consumers. It'd be a
nightmare for a consumer to have to worry about catching an SqlException,
XmlException, OledbException....must better to let them worry about a
ProviderException.

About your specific example...I think it's legitimate because your code
participated in the exception (by doing some discovery to find out exactly
what the cause was). In poor cases I've seen, exceptions are repacked for
with little additional information. I think you are adding sufficient
meaning to make it worthwhile..

karl
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,756
Messages
2,569,535
Members
45,008
Latest member
obedient dusk

Latest Threads

Top