Search code examples
wcfexceptionbusiness-logic-layerfaultexceptionfaultcontract

Exception handling with WCF plus Business Logic Layer scenario


My services simply call BusinessLogicLayer methods where entire business logic is put. I want to know what's the best practice for handling exceptions raised by BL?(not only fatal exceptions, also "logic" ApplicationExceptions like UserNotFoundException which my BL throws when can't find user).

Where should I transform these exceptions into FaultExceptions which client will see?

Should I throw my business Exceptions from BL and than catch them into service call and transform to FaultException and return to client? or BL should raise already "client friendly" FaultExceptions?

thanks in advance :)


Solution

  • I would say throw business exception from business logic layer, this would keep your business logic layer decoupled with wcf implementation. In service call you may override applydispatchbehaviour and add error handler there, something like

    Overriding IServiceBehavior.ApplyDispatchBehavior

     void IServiceBehavior.ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
            {
                foreach (ChannelDispatcher dispatcher in serviceHostBase.ChannelDispatchers)
                {
                    dispatcher.ErrorHandlers.Add(new FaultErrorHandler());
                }
            }
    

    FaultErrorHandler

    public class FaultErrorHandler : IErrorHandler
        {      
    
            void IErrorHandler.ProvideFault(System.Exception error, MessageVersion version, ref Message fault)
            {
                if (fault == null)
                {
                    FaultException<[ExceptionType]> fe = new
                        FaultException<[ExceptionType]>([Exception cass],
                        error.Message, FaultCode.CreateReceiverFaultCode(new FaultCode("ServerException")));
                        MessageFault mf = fe.CreateMessageFault();
                        fault = Message.CreateMessage(version, mf, fe.Action);
    
                }
            }
    
        }