Search code examples
wcfdomain-driven-designdtodatacontract

WCF Best Practice for Data Contracts, Shared Classes, and DTOs


Before I break my application, my current namespace look something like this:

CompanyAbc.Core
CompanyAbc.AppXyz.Web
CompanyAbc.AppXyz.Business

The CompanyAbc.Core namespace contain common code used by all applications in our company. An example would be a class called "ClientMessage" which we use as a container to carry messages from one tier to another tier (e.g. to abstract out and support showing success or error messages when saving data at the data-tier all the way to the UI-tier)

We are now making the CompanyAbc.AppXyz.Business into a WCF Service. My question is this: What is the best practice for 'sharing' (or not sharing) these base/common entities?

For example, would you:

a) add the [DataContract] attributes directly to classes in the CompanyAbc.Core namespace, even though it has nothing to do with WCF.

   CompanyAbc.Core.Entities
            ClientMessage.cs

OR

b) create a Data Transfer Object that is an exact copy from the CompanyAbc.Core namespace?

   CompanyAbc.Core.Entities
            ClientMessage.cs
   CompanyAbc.AppXyz.Business.DataContracts
            ClientMessageDto.cs

OR

c) Other options?

Another complexity is that we intend to share these assemblies. But to enforce decoupling and not share assemblies/business entities, would you go all out crazy and do something like this?

   CompanyAbc.Core
   CompanyAbc.Core.Shared.Entities
      ClientMessage.cs

   CompanyAbc.AppXyz.Web
   CompanyAbc.AppXyz.Web.Entities
      ClientMessage.cs --> derives from the Core.Shared, or just duplicate code?

   CompanyAbc.AppXyz.Business.Entities
      ClientMessage.cs --> derives from the Core.Shared, or just duplicate code?
   CompanyAbc.AppXyz.Business.DataContracts
      ClientMessageDto.cs

Solution

  • Here is how my namespaces look like, as I used it so far:

    ABC.Core
    ABC.Data
    ABC.Business
    ABC.Web;
    ABC.Services (common)
    ABC.Services.DTO (common)
        ABC.Services.Svc1
            ABC.Services.Svc1.DTO
        ABC.Services.Svc2
            ABC.Services.Svc2.DTO
    

    In practice you won't like to have so many shared classes between the services, because they would probably want to be separated one of the other. The better are independent one of the other, the better you can version them, but is true that it would require a bit of duplicated code in the DTO level of each service. Many people use Automapper to project the Core classes into DTOs.

    Let me know what you think.