I've noticed that a handful of WCF applications choose to "break" their objects apart; that is, a project might have a DataObjects assembly that contains DataContracts/Members in addition to a meaningful class library that performs business logic.
Is this an unnecessary level of abstraction? Is there any inherent evil associated with going through and tagging existing class libraries with DataContract information?
Also, as an aside, how do you handle error conditions? Are thrown exceptions from the service (InvalidOperation, ArgumentException and so on) generally accepted, or is there usually a level around that?
The key reason to separating internal business objects from the data contracts/message contracts is that you don't want internal changes to your app to necessarily change the service contract. If you're creating versioned web services (with more than 1 version of the implemented interfaces) then you often have a single version of your apps business objects with more than 1 version of the data contract/message contract objects.
In addition, in complex Enterprise Integration situations you often have a canonical data format (Data and Message contracts) which is shared by a number of applications, which forces each application to map the canonical data format to its internal object model.
If you want a tool to help with the nitty gritty of separating data contract/message contract etc. then check out Microsoft's Web Services Software Factory http://msdn.microsoft.com/en-us/library/cc487895.aspx which has some good recipes for solving the WCF plumbing.
In regards to excpetions, WCF automatically wraps all exceptions in FaultExceptions, which are serialized as wire-format faults.
It's also possible to throw generic Fault Exceptions which allows you to specify additional details to be included with the serialized fault. Since the faults thrown by a web service operation are part of its contract it's a good idea to declare the faults on the operation declaration:
[FaultContract(typeof(AuthenticationFault))]
[FaultContract(typeof(AuthorizationFault))]
StoreLocationResponse StoreLocation(StoreLocationRequest request);
Both the AuthenticationFault and AuthorizationFault types represent the additional details to be serialized and sent over the wire and can be thrown as follows:
throw new FaultException<AuthenticationFault>(new AuthenticationFault());
If you want more details then shout; I've been living and breathing this stuff for so long I almost making a living doing it ;)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With