Consider this scenario: I have 3-layer app, when the user click on the button the button event handler calls a method in biz layer that do whatever with data my button even
The exception handling mantra is: "Throw early, catch late". You want to catch exceptions at the last possible moment, but you want to throw them immediately (don't perform a bunch more processing after determining something is wrong and then throw an exception). If you cannot "handle" the exception, then don't catch it.
In most circumstances, Try...Finally blocks should be far more common in your code than Try...Catch.
Put the try-catch where you are sure you won't just swallow the exception. Multiple try-catch blocks in various layers may be OK if you can ensure consistency.
For example, you may put a try-catch in your data access layer to ensure you clean up connections properly. But as you can't do much more there you should probably rethrow the exception.
Moving to business layer, you may put try-catch across multiple database operations which you want to proceed atomically. In this case, may be you should rollback everything or put things in a consistent state, log the exception somewhere. Swallowing or rethrowing should be decided on case by case basis.
Your presentation layer should always catch all exceptions, be it some web application, script running in a browser or some rich client application. You may not be able to understand the exception completely, but at least you can ensure that your application does not die in the face of a user.
Of course, its just a piece of advice. YMMV. :)
UI is just for presentation. You don't catch exceptions there, because figuring out what to do with it means logic. That belongs in business or controller layers. At worst, you catch the exception and map it to an appropriate, user-friendly error message that is then sent to the presentation for display.
Probably best to use try catch in all layers but only silently catch the exceptions in the UI layer. In the biz and data access layers you should probably catch the exception and record the information, before re-throwing e.g.
try
{
//do something
}
catch(Exception ex)
{
LogFile.WriteLine(ex.ToString());
throw;
}
Note: do not write:
throw ex;
as this will clear all the useful stack information from the exception.
Always try/catch at the top level or contoller level.
It just depends on where you actually want to do something about it. Generally I catch it in the business layer, and then log it and possibly call some ui function to display a message to the user.
I consider what to do with errors a business rule. It should be separate from the data layer or ui layer.