views:

1341

answers:

2

I have a project where we use screen DTO's to encapsulate the data between the Service Layer and the Presentation Layer. In our case, the presentation layer is ASP.Net.

The only classes that know about the DTO's are the service layer classes and the Pages/Controls that call these services and display the DTO's.

The DTO's are almost always Page/Control specific so I feel they belong in the Presentation Layer, but that would mean the Service Layer would have to reference the Presentation Layer in order to use the DTO's.

I'm almost thinking that the Service Layer should return richer objects (but not domain entities?) and then the Presentation Layer can take these objects and map them to very specific DTO's for each Page/Control concern.

Here's an interface declaration and a DTO so you can see what I'm talking about:

public interface IBlogTasks
{
    BlogPostDisplayDTO GetBlogEntryByTitleAndDate(int year, int month, string urlFriendlyTitle);
}

public class BlogPostDisplayDTO 
{
    public string Title { get; set; }
    public DateTime PostDate { get; set; }
    public string HtmlContent { get; set; }
    public string ImageUrl { get; set; }        
    public string Author { get; set; }
    public int CommentCount { get; set; }
    public string Permalink { get; set; }
}

Edit

Here's another code sample to describe a use case where the Domain model isn't involved. Maybe this will clarify things a bit. I believe I've overloaded the DTO meaning. I'm not talking about a DTO for the function of transfering an object over the wire. I'm creating DTOs to formalize contracts between communication to my Service Layer.

public interface IAuthenticationTasks
{
    bool AuthenticateUser(AuthenticationFormDTO authDTO);
}

public class AuthenticationFormDTO
{
    public string UserName { get; set; }
    public string Password { get; set; }
    public bool persistLogin { get; set; }
}

Let's say my authentication all of the sudden requires an IP address parameter. I can now add that property to the DTO without having to change my contract interface.

I don't want to pass Entities to my Presentation Layer. I don't want my code behind to have the ability to go BlogPost.AddComment(new Comment())

+3  A: 

Are you using actual services (web or WCF)? If so, then define the DTOs in the service layer and the proxy created when you add a service (or web if using old ASMX) reference will contain all of the DTO types. This is the simplest way to do it and maintains only loose coupling between your ASP.NET project and your service project -- no direct project reference is required in either direction. As you update your DTOs, all you need to do is update your service reference and it will automatically expose the updates to your web project via the proxy class that is generated.

In any event, if you're following something like a DDD approach it is best to have your infrastructure projects (such as a web-platform-specific UI) referencing your domain objects than vice versa. If you follow my advice above, however, your web project won't have a direct dependency on the project at all, which is a good thing, and certainly better than having your rich domain objects depending on your web project (if that were even a consideration - I realize you weren't saying you were doing this).

If your DTOs are view-specific, then I would include them in your UI project. It should really be the controller's job to ensure that the View only gets from the Model what it needs - in your case a value-object with just the fields needed by the view.

ssmith
I'm not talking about Services as an implementation. My Service Layer is just a thin service between the UI and the Domain. You're correct that I'm following a DDD approach, but I'm not letting my Domain Entities outside the Service Layer.
Scott Muc
Then it would make your DTOs just entity objects, there is no transfer per say. They reside there in the service layer, and presentation fabricate their own objects based on entity objects provided by service layer, and those objects dwell at presentation layer. Am I right?
Adeel Ansari
I've edited my question to describe my desired usage of DTOs.
Scott Muc
I would fall back then on the fact that these DTOs are specific to your UI layer, and therefore should live there. If you can't create a design in which your Domain Objects depend on your Infrastructure and UI layer, then put the DTOs into a 3rd project of their own and have UI Domain dpend on that
ssmith
i updated my answer - see the last paragraph. You want the DTOs in the UI project. You want your controller to be the gatekeeper between your Domain objects and your View. That's its job.
ssmith
I think I get it then. So through the layers, an Entity is passed from the DataAccess Layer to the Service Layer which maps it to a ValueObject then the PresentationLayer takes that object and maps it to all the DisplayDTOs that are needed by the UI.
Scott Muc
+4  A: 

Even thought the canonical use-case for the 'DTO' is more "serializable object that can be passed over the wire", in this case you are really referring more to 'presentation-transfer-objects' or 'view-models'.

Typically for our projects the answer to where these live is where the 'translation' code is that maps the DDD domain model to the PTO classes. If that's in the Prensenation layer (perhaps not so great an answer) then the pres. layer is where I'd declare the PTOs. But more often than not, its the 'Service' that does the translation for you and that means that both the 'Service' and the 'Presentation' layer need references to the PTOs and that (usually) leads to their declaration in a separate, neutral project/assembly/namespace/whatever that BOTH the presentation layer AND the service layer can then reference.

sbohlen
Thanks! I think part of my confusion is using the term DTO in the wrong context. PTO and ViewModel gives me some better terms to read further on this.
Scott Muc