Last post Mar 07, 2012 11:34 AM by atconway
Mar 07, 2012 12:37 AM|snkar|LINK
Reading through different threads related to Exception Handling best practices in ASP.NET, I am a bit confused about the best strategy to implement for a classical multi-tiered asp.net app.
My initial idea was to handle exceptions at layer boundaries, log them right at the point of infraction and wrap/replace the exception into layer specific exception types to be handled by callers up the stack. For example,
all my public methods in my DAL, BLL and Presenter layer(my application follows MVP) have try catch blocks and catch on the broad Exception type(which is in itself a bad idea but I chose it to ensure that exceptions crossing layer boundaries
are cast into the layer specific exception type). Callers up the stack like the the UI can either choose to handle the exception(if it is of type Validation Exception -- needs to be displayed to the user) or let it be handled by the Global Exception Handler(Application_Error
handler in the Global.asax) where the error is mailed to the dev/support team and a user friendly custom error page is displayed to the user.
This seemed to me to be a reasonable design. But on a little bit of research, I found that
a best practice guideline says not to catch exceptions unless you can gracefully recover from them and allow some global exception handler to take the necessary steps as per the desired design. So that would mean that all the code below the
UI(the top layer of the call stack) should just ignore exceptions and let the exception bubble up to the global handler where it can get logged, mailed and notified appropriately to the user.
While this is definitely a much more easier approach to implement, I have seen a lot of good apps having custom layer specific exception types which are being thrown when the code crosses a layer boundary. These types are just derived from the Base exception
type and are not adding any additional information about the exception. These are being used only for the callers above the stack to decide the correct choice of action -- whether to log/wrap/replace/rethrow the exception.
So my question is under what circumstances is the Custom Exception types a better choice and when should I resort to a having only a global exception handler to handle all my exceptions?
Mar 07, 2012 05:29 AM|DarrellNorton|LINK
It depends on whether the boundaries you are referring to are project boundaries or service boundaries. Projects are just a way to logically divide up your code. Services are actually a boundary at which you may no longer control who calls you, so you
must prevent the exceptions from exposing any security information.
The pattern is called Exception Shielding. See how to implement it for web services here: http://msdn.microsoft.com/en-us/library/ff650043.aspx
For project boundaries, it is usually more useful to catch only the exceptions you can do something about and then let the rest "bubble up."
For service boundaries, it is almost always a good idea to implement Exception Shielding.
Mar 07, 2012 11:34 AM|atconway|LINK
But on a little bit of research, I found that a best practice guideline says not to catch exceptions unless you can gracefully recover from them and allow some global exception handler to take the necessary steps as per the desired design.
I agree with this. If all you are doing is logging exceptions then you can do this in the 'Application_Error' event in the Global.asax file for an ASP.NET application. As Darrell mentioned the line to differentiate can be if the layers/boundaries are just
different class libraries within a solution or actual WCF Service calls outside of the application.
Typically if I have a simple UI-BLL-DAL .NET solution with (3) different projects, I will rely on the global handler for logging exceptions if that is all I need to do. Of course I
always have proper exception handling within any layer where I can do something meaningful with the exception and where logging is not desired (i.e. failing connection to a database or service and allowing a retry in certain conditions).
However when I have a WCF service that lives on its own and not specific to any single application, I will have it implement its own exception handling, as well as preserve the exception and pass it on to the client as well. This serves (2) purposes: 1 I
want the service to report independently when it has an issue, because it cannot rely on the client to do something meaningful with the thrown exception (they might not even handle it). 2. Alert the client obviously when something bad has happened so they
can react accordingly.
As a side note for a generic logger if that is all you need, have a look at the Enterprise Library's
Exception Handling Application Block
Hope this helps!