I need a point of view in this design that I am proposing for handling exceptions.
I have a wcf service that throws different types of fault exceptions:
- throw new FaultException < BusinessRuleViolationFault >(...)
- throw new FaultException < SomeOtherViolationFault >(...)
- ...
- ...
All these fault exception classes implement an interface called IViolationFault, which has a single HandleException method. The implementation of each such method is different depending on the class they are in; so for example when these exception classes are caught in the client, all I need to do is just call that HandleException() method and it will be taken care of without me having to write an IF condition to differentiate between the types of errors. In BusinessRuleViolationFault's HandleException() method I might just want to show a message on the screen, while in the other one I might want to log it somewhere and trigger some other action as well...
catch (FaultException<BusinessRuleViolationFault> ex)
{
ex.HandleException();
}
catch (FaultException<SomeOtherViolationFault> ex)
{
ex.HandleException();
}
Questions
- Is there any thing wrong in this approach?
- Is there a way I can reduce the number of catch blocks and have just one catch block take care of all exception types?
- Is this a good object oriented way to acheive polymorphism while handling exceptions?
EDIT
Ive changed the code to inherit from a base class instead of implementing an interface. My BusinessRuleViolationFault class has the HandleException method, but I am not able to get the HandleException method in the client catch block. What am doing wrong? This is how it is thrown in the service
BusinessRuleViolationFault bf = new BusinessRuleViolationFault("");
throw new FaultException<BusinessRuleViolationFault>(bf, new FaultReason(new FaultReasonText("Fault reason here")));
This is my BusinessRuleViolationFault code
[DataContract]
public class BusinessRuleViolationFault : BaseFault
{
public BusinessRuleViolationFault(string message)
: base(message)
{
}
[OperationContract]
public override string HandleException()
{
return "BusinessRuleViolationFault executed";
}
}
[DataContract]
public abstract class BaseFault
{
public BaseFault(string message)
{
Message = message;
}
[DataMember]
public string Message { get; set; }
[OperationContract]
public abstract string HandleException();
}
Do let me have your thoughts on this. Thanks for your time...
There is nothing wrong with this approach, it is just a normal use of polymorphism.
You can reduce the number of catch blocks by having all your custom exception classes derive from a base exception class instead of just implementing an interface. For example:
This way you can catch all your exceptions with just the following:
EDIT: Correct sample code.
At least with WCF, where this is the way to implement custom faults, there is nothing wrong to do it that way. Although, you loose polymorphism, as you cannot to something like this
to catch your FaultExceptions.
You also (obviously) cannot change the base class
System.ServiceModel.FaultException<TDetail>
or evenSystem.ServiceModel.FaultException
to include anyHandleException()
method.What you can do is, to work with reflection to extract the
TDetail
of the FaultException, if any, and then work with that:You might want to take a look at the functional approach documented in this blog post that allows you to make your try/catch logic a little clearer/terse. eg: