Where to catch exceptions
I have a WCF svc separated into a Service Layer, Business Logic Layer and Data Access Layer.
When my DAL encounters an exception, should I catch it there or let it bubble back up to the Service Layer? And why?
Please disregard any client involvement for this scenario, I am only con开发者_开发问答cerned with logging the exceptions on the WCF svc.
There is a term for that - Exception Shielding. Basically you should prevent SYSTEM exceptions to travel to higher level, because this could give an atacker a view of your system architecture. WCF Exception Shielding can catch exceptions of certain type and replace them with exceptions of other type. For example it could catch StackOverflow exception and replace it with your custom SystemException. If you use Enterprise Library you could also configure to log these exceptions when they are replaced
Using the Exception Handling Block in Enterprise Library 3.0
It depends also on how you are architecting your solution. For instance, if the DAL and BLL layers are meant to be totally independent components, then they cannot make assumptions about who is calling them. As such, they should both catch exceptions on the component boundary, log those exceptions, then allow the exception to propagate. They may want to wrap the general exception in a layer-specific exception:
catch (Exception ex)
{
Logger.Log(ex);
throw new DalException("Unhandled exception in DAL", ex);
}
If you know these will only be used as part of your overall application, then you can defer logging to the outermost layer - the layer that, if it doesn't catch the exception, the exception won't be logged.
I guess it depends on how the service is consumed and who (if anyone) you want to made aware when an exception occurs.
For example, if you're developing a mission-critical internal business application, you may want the details of the exception to bubble through the service layer to the user-interface that consumes the application so they end-user can contact a developer to quickly get the problem resolved.
However, let's say your service is consumed by a public web page. You probably still want the service layer to catch the error in some way, but you might choose to pass minimal information to the end client, provide a generic error message to the end user, and write the details of the exception to an error log for developers to review.
In the end, I still think you want the exception to bubble up to the service layer, but how you handle the exception and decide what information to pass to the end client is up to you.
I usually use a generic error handler (System.ServiceModel.Dispatcher.IErrorHandler
implementation) that is attached to web services by a ServiceBehavior in the configuration file.
The IErrorHandler.ProvideFault
method intercepts exceptions thrown from the service and:
Logs them;
Passes FaultExceptions through as-is;
Converts "business" exceptions (e.g. business rule violations) thrown by the BLL to FaultExceptions with a fault code "sender/client";
Converts technical exceptions (e.g. thrown by the DAL) to FaultExceptions with a fault code "receiver/server".
In this way the service code itself only contains the business code and does not need to catch any exceptions.
精彩评论