WCF: SOAP Fault or normal Exception(s) in DataContract class
The main parameter to my Service's OperationContract is a class called Preapproval. In the Preapproval class, there are a few public getters/setters for the DataMember attributes. I have code that validates the input to the setters, such that I would throw an ArgumentException, if say, a parameter is blank or out of the proper bounds for the domain.
If the inputs are invalid, I usually would throw an ArgumentException here. Since this is a WCF situation, must I throw a pre-defined FaultException here rather than ArgumentException? I under开发者_开发知识库stand that, elsewhere, I may catch general exceptions and rethrow them as FaultExceptions, but this activity will occur higher up the stack, in some work performed automatically by WCF plumbing.
For example, when a caller invokes my service, the serializer will deserialize their SOAP, attempt to call the setters on my object, and experience the throwing of the ArgumentException, way before my operation is actually invoked. Thus, is it good design practice, in DataContract classes, to simply throw FaultExceptions right away? I really don't want to wire a custom handler up to the channel dispatcher.
I understand that I could simply throw FaultExceptions directly, but I would really like to confine that sort of thing to the service. If it cannot be avoided, I can do it in the supporting classes as well, but I would prefer to write typical code as much as possible, that is not so tightly coupled to System.ServiceModel, etc.
Thanks!
I would leave the FaultExceptions out of your DataContract class -- you might want to use those classes outside of a WCF context.
One approach that would prevent WCF specific code from sneaking into your DataContracts (besides attributes) would be to have the DataContract class throw exceptions and in the service layer use Enterprise Library's WCF Exception Shielding to map those exceptions to fault contracts.
Basically Enterprise Library implements IErrorHandler
and converts Exceptions to FaultExceptions. I think a handler is the only way to achieve what you want (since the exceptions are not thrown in your service). The good news is that you really don't have to do much to get it working.
Just add an attribute to your service:
[ServiceContract]
[ExceptionShielding]
public interface IApproval
{
[OperationContract]
[FaultContract(typeof(ApplicationServiceFault))]
[FaultContract(typeof(SystemServiceFault))]
void PreApprove(Preapproval preapproval);
}
and then add some configuration (configuration omitted to save space) to map Exceptions to a FaultContract. Note that your operations will still have to declare FaultContracts.
Your PreApproval
class should not be aware that it's being used in a web service. Let it throw whatever exception it would have thrown if it were being called from any other type of application.
The "top level" of your service should catch exceptions and translate them to the appropriate FaultException
.
精彩评论