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 ;)
Related
I have a web client that calls my WCF business service layer, which in turn, calls external WCF services to get the actual data. Initially, I thought I would use DTOs and have separate business entities in the different layers... but I'm finding that the trivial examples advocating for DTOs, to be, well, trivial. I see too much duplicate code and not much benefit.
Consider my Domain:
Example Domain
I have a single UI screen (Asp.net MVC View) that shows a patient's list of medications, the adverse reactions (between medications), and any clinical conditions (like depression or hypertension) the patient may have. My domain model starts at the top level with:
MedicationRecord
List<MedicationProfile> MedicationProfiles
List<AdverseReactions> Reactions
List<ClinicalConditions> ClinicalConditions
MedicationProfile is itself a complex object
string Name
decimal Dosage
Practitioner prescriber
Practioner is itself a complex object
string FirstName
string LastName
PractionerType PractionerType
PractionerId Id
Address Address
etc.
Further, when making the WCF requests, we have a request/response object, e.g.
MedicationRecordResponse
MedicationRecord MedicationRecord
List<ClientMessage> Messages
QueryStatus Status
and again, these other objects are complex objects
(and further, complicates matter is that they exist in a different, common shared namespace)
At this point, my inclination is that the MedicationRecordResponse is my DTO. But in pure DataContracts and DTO and separation of design, am I suppose to do this?
MedicationRecordResponseDto
MedicationRecordDto
List<ClientMessageDto>
QueryStatusDto
and that would mean I then need to do
MedicationProfileDto
PractitionerDto
PractitionerTypeDto
AddressDto
etc.
Because I have show almost all the information on the screen, I am effectively creating 1 DTO for each domain object I have.
My question is -- what would you do? Would you go ahead and create all these DTOs? Or would you just share your domain model in a separate assembly?
Here's some reading from other questions that seemed relevant:
WCF contract know the domain
Alternatives for Translation Layer in SOA: WCF
SOA Question: Exposing Entities
Take a look on excellent articles
Why You Shouldn’t Expose Your Entities Through Your Services
DTO’s Should Transfer Data, Not Entities
above links don't work, looks like a domain issue (I hope it'll be fix), here is the source:
DTO’s Should Transfer Data, Not Entities
Why You Shouldn’t Expose Your Entities Through Your Services
I've always had an aversion to the duplicate class hierarchy resulting from DTOs. It seems to be a flagrant violation of the DRY principle. However, upon closer examination, the DTO and the corresponding entity or entities serve different roles. If you are indeed applying domain-driven design then your domain entities consist of not only data but behavior. By contrast, DTOs only carry data and serve as an adapter between your domain and WCF. All of this makes even more sense in the context of a hexagonal architecture also called ports and adapters as well as the onion architecture. Your domain is at the core and WCF is a port which exposes your domain externally. A DTO is part of how WCF functions and if you agree that it is a necessary evil your problem shifts from attempting to eliminate them to embracing them and instead focusing on how to facilitate the mapping between DTOs and domain objects. A popular solution is AutoMapper which reduces the amount of boiler plate mapping code you need to write. Aside from the drawbacks, DTOs also bring a lot of benefits. One is that they furnish a buffer between your domain entities and the outside world. This can be of great help in refactoring because you can keep your core domain very well encapsulated. Another benefit is that you can design your DTOs such that they fulfill requirements of the service consumer, requirements which may not always be in full alignment with the shape of your domain objects.
Personally, I don’t like using MessageContract as entities. Unfortunately, I have an existing WCF service that use MessageContract as entities – i.e. data is filled into the MessageContract directly in the data access layer. There is no translation layer involved.
I have an existing C# console application client using this service. Now, I have a new requirement. I need to add a new field in the entity. This is not needed by the client. The new field is only for the internal calculations in the service. I had to add a new property named “LDAPUserID” in the MessageContract which also act as a entity.
This may or may not break the client depending on whether the client support Lax Versioning. Refer Service Versioning.
It is easy to mistakenly believe that adding a new member will not break existing clients. If you are unsure that all clients can handle lax versioning, the recommendation is to use the strict versioning guidelines and treat data contracts as immutable.
With this experience, I believe it is not good to use MessageContract as entities.
Also, refer MSDN - Service Layer Guidelines
Design transformation objects that translate between business entities and data contracts.
References:
How do I serialize all properties of an NHibernate-mapped object?
Expose object from class library using WCF
Serialize subset of properties only
I am in the processing of migrating from web services to WCF, and rather than trying to make old code work in WCF, I am just going to rebuild the services. As a part of this process, I have not figured out the best design to provide easy to consume services and also support future changes.
My service follows the pattern below; I actually have many more methods than this so duplication of code is an issue.
<ServiceContract()>
Public Interface IPublicApis
<OperationContract(AsyncPattern:=False)>
Function RetrieveQueryDataA(ByVal req As RequestA) As ResponseA
<OperationContract(AsyncPattern:=False)>
Function RetrieveQueryDataB(ByVal req As RequestB) As ResponseB
<OperationContract(AsyncPattern:=False)>
Function RetrieveQueryDataC(ByVal req As RequestC) As ResponseC
End Interface
Following this advice, I first created the schemas for the Request and Response objects. I then used SvcUtil to create the resulting classes so that I am assured the objects are consumable by other languages, and the clients will find the schemas easy to work with (no references to other schemas). However, because the Requests and Responses have similar data, I would like to use interfaces and inheritance so that I am not implementing multiple versions of the same code.
I have thought about writting my own version of the classes using interfaces and inheritance in a seperate class library, and implementing all of the logging, security, data retrieval logic there. Inside each operation I will just convert the RequestA to my InternalRequestA and call InternalRequestA's process function which will return an InternalResponseA. I will then convert that back to a ResponseA and send to the client.
Is this idea crazy?!? I am having problems finding another solution that takes advantage of inheritance internally, but still gives clean schemas to the client that support future updates.
The contracts created by using WCF data contracts generally produce relatively straight-forward schemas that are highly interoperable. I believe this was one of the guiding principles for the design of WCF. However, this interoperability relates to the messages themselves and not the objects that some other system might produce from them. How the messages are converted to/from objects at the other end entirely depends on the other system.
We have had no real issues using inheritance with data contract objects.
So, given that you clearly have control over the schemas (i.e. they are not being specified externally) and can make good use of WCF's inbuilt data contract capabilities, I struggle to see the benefit you will get the additional complexity and effort implied in your proposed approach.
In my view the logic associated with processing the messages should be kept entirely separate from the messages themselves.
I know that WCF or any web service platform does not prevent the developers from mixing fetch and update in same operation. What I mean is mentioned below
List UpdateDate( SomeType Datacontract)
Syntactically this is correct format an is supported in WCF. But is it ok to do this in service oriented world, also is industry wide standard to support this.
One problem I see right away is we violate the very first law of SOA which is atomicity but are there any other issues associated?
It's wider than just WCF: any method that appears to be a Get/Fetch (i.e. by its name) should ideally not perform updates.
The classic Bad example is a Property Getter than alters the state of objects, thus introducing the possibility of unwanted side effects.
Please note that my experience in Silverlight/.Net and WCF is about two weeks of googling and deciphering tutorials. I need to attempt and provide feedback to a client on if Silverlight will be a possible solution to their application needing a RIA front end.
The client has a rather large .Net based application with a UI layer built which greatly relies on the creation and manipulation of specific (personal) classes and objects from the backend (which would be the server side).
A summery of what I understand to be the general procedure: one can pass simple objects containing simple data types, or more complex .Net type objects. Basically anything which can be understood by both client and server side, after serializing.
But what is the limitation to the complexity of an object I can pass? Or phrased otherwise, would silverlight and WCF be able to support the passing of a personalized object which may contain references to other classes/objects and variables etc?
Additional Info (in case it can help):
I am not allowed direct access to their backend code but with the information I have been given I can safely say their classes heavily use inheritance and overloading of functions/methods in the classes.
As far as I know there is nothing specific to Silverlight. There are some things to keep in mind though.
WCF serialization doesn´t like circular references.
All types need to specified in the contract. So watch out with inheritance etc.
In general using DTO's (Data Transfer Objects) and not exposing your business objects is the way to go.
The metaphor is one of message passing as opposed to passing objects. DTO's as Maurice said.
You can get pretty complex, but each object needs to have its contract defined.
What is the proper way to handle polymorphic business objects in a WCF/SOAP world?
It seems to me that SOA and OOP are at odds with each other - to expose a clean WSDL you need concrete objects, typically not even utilizing inheritance. On the other hand, presumably in the underlying system, you'll want to follow proper OO design.
What do people typically do here? Build a set of WCF contract objects, forgoing OOP principles, then convert to and from another set of objects in the actual logic layers?
What do people typically do here? Build a set of WCF contract objects, forgoing OOP principles, then convert to and from another set of objects in the actual logic layers?
Yes.
The way WCF serializes things ends up putting a lot of limitations on what you can and can't do with the contract objects. What you can't do ends up being "most anything useful".
I've found it makes things much clearer if you think of the WCF-contract objects as just a data transfer mechanism. Basically like strongly/statically typed XML.
Instead of converting your business object to an XML string (and back again), you convert your business object to a WCF-contract object (and back again), but it's otherwise similar
After reading the Thomas Erl library, I came to the following conclusion:
Think of the WCF Contracts/SOAP Message as simply a message that the Services use to communicate (don't tightly tie that to Objects in your code).
You can then use OOP to design a code-base that gracefully handles those messages using common OOP techniques.
You use an abstraction (interface type) annotated with WCF attributes in order to define your Service contract.
This is both depending on abstraction, which is according to OOP, as well as defining a service endpoint, which is SOA.
In general, if you find that you are getting business objects with dependencies, you should consider pulling such dependencies up to the service business layer as opposed to inject dependencies into the business objects.
The service business layer will then act as a mediator acting on both the WCF service proxy as well as the business objects. As opposed to having the business objects acting on the WCF service proxy.
All great comments on this topic! I'll add my vote to the notion of an adapter for mediation between your service orientation and object orientation. I also like Thomas Erl's approach where in his service model he introduces the notion of "application services" and "business services." These are the way to go for your integration points with your specific application/business environment (i.e. your object oriented and component oriented framework/API). This way should result in much better composability and thus capability, for you enterprise framework gurus out there.