|
We received feedback regarding our initial V1.0 exception handling implementation where there was some code that was a bit redundant and could be consolidated in a single place.
Our current approach in V2.0 has all the Exception Handling located in a single point, a
WCF behavior attibute which calls to an Error-Handler.
Therefore, our WCF Service looks like the following:
[ApplicationErrorHandlerAttribute()] // manage all unhandled exceptions
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
[UnityInstanceProviderServiceBehavior()] //Instances injection behavior
public class ERPModuleService : IERPModuleService
{
ICustomerAppService _customerAppService;
ISalesAppService _salesAppService;
public ERPModuleService(ICustomerAppService customerAppService,
ISalesAppService salesAppService)
{
if (customerAppService == null)
throw new ArgumentNullException("customerAppService");
if (salesAppService == null)
throw new ArgumentNullException("salesAppService");
_customerAppService = customerAppService;
_salesAppService = salesAppService;
}
public CustomerDTO AddNewCustomer(CustomerDTO customer)
{
//A single line of code publishing ‘Application Services Façade’
return _customerAppService.AddNewCustomer(customer);
}
//OTHER WCF methods
//...
}
Then, you can see that we are implementing the
[ApplicationErrorHandlerAttribute()]
in order to handle the exceptions.
This is the implementation of that attribute:
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
public sealed class ApplicationErrorHandlerAttribute
: Attribute, IServiceBehavior
{
public void ApplyDispatchBehavior(ServiceDescription serviceDescription,
System.ServiceModel.ServiceHostBase serviceHostBase)
{
if (serviceHostBase != null
&&
serviceHostBase.ChannelDispatchers.Any())
{
//add default error handler for all dispatchers in wcf services
foreach (ChannelDispatcher dispatcher in serviceHostBase.ChannelDispatchers)
dispatcher.ErrorHandlers.Add(new ApplicationErrorHandler());
}
}
// OTHER METHODS OMMITTED
}
}
Then, we are using the ApplicationErrorHandler class (IErrorHandler):
public sealed class ApplicationErrorHandler
: IErrorHandler
{
public bool HandleError(Exception error)
{
if (error != null)
LoggerFactory.CreateLog().LogError(Messages.error_unmanagederror, error);
//set error as handled
return true;
}
public void ProvideFault(Exception error,
System.ServiceModel.Channels.MessageVersion version,
ref System.ServiceModel.Channels.Message fault)
{
if (error is FaultException<ApplicationServiceError>)
{
MessageFault messageFault = ((FaultException<ApplicationServiceError>)error).
CreateMessageFault();
//propagate FaultException
fault = Message.CreateMessage(version, messageFault, (
(FaultException<ApplicationServiceError>)error).Action
);
}
else
{
//create service error
ApplicationServiceError defaultError = new ApplicationServiceError()
{
ErrorMessage = Resources.Messages.message_DefaultErrorMessage
};
//Create fault exception and message fault
FaultException<ApplicationServiceError> defaultFaultException =
new FaultException<ApplicationServiceError>(defaultError);
MessageFault defaultMessageFault = defaultFaultException.CreateMessageFault();
//propagate FaultException
fault = Message.CreateMessage(version, defaultMessageFault,
defaultFaultException.Action);
}
}
}
Any feedback about this new implementation that we made for V2.0?.
We’d really appreciate any constructive feedback about it.
Thanks a lot!, :-)
Cesar.
|