WCF Message & Data Contract, DTO, domain model, and shared assemblies
Asked Answered
G

3

5

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:

  1. WCF contract know the domain
  2. Alternatives for Translation Layer in SOA: WCF
  3. SOA Question: Exposing Entities
Gumption answered 27/7, 2012 at 4:32 Comment(1)
any full sample application with source code using DTOs, MessageContracts, and Mappers in layers ? WCF SOAP better than REST ?Physiotherapy
C
6

Take a look on excellent articles

above links don't work, looks like a domain issue (I hope it'll be fix), here is the source:

Commove answered 27/7, 2012 at 5:39 Comment(1)
The links appears to be broken. Could you please update?Demonology
R
3

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.

Roughish answered 27/7, 2012 at 5:9 Comment(5)
Thank you for the insight, I generally agree. However, in this particular case, our UI layer and Business layer are actually fairly dumb in the sense that we are really just writing a Viewer to display data from a 3rd party system. (e.g. a Pharmacy system). Our domain models have no behavior, just simple POCOs. Does this change your view at all? What happened to the KISS and YAGNI principles? If I have a 100 domain model entities, do I really want 100 DTOs? And if I continue with this approach, my web tier should not share entities either, so now I have a whopping 300 entities!Gumption
If there is no behavior and there are many objects then that changes my opinion. In that case I would decorate domain objects with data contract attributes directly. Also, there are libraries that provide framework for this kind of problem, such as WCF Data Services.Roughish
Also I think some, including my self, would hesitate to call this domain-driven design.Roughish
Yes, you are very correct -- in many cases, my objects/classes are more like DTOs than domain model entities.Gumption
any full sample application with source code using Onion and/or Hexagonal Architecture?Physiotherapy
D
3

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:

  1. How do I serialize all properties of an NHibernate-mapped object?
  2. Expose object from class library using WCF
  3. Serialize subset of properties only
Demonology answered 5/4, 2013 at 8:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.