Think Before You Use The DTO Pattern

Let me preface this blog post by saying that there are still times when a DTO makes sense. Also, this post is written from a .NET perspective, so some things may be different on your platform. What I want to address though is the tendency of many developers to just automatically create a set of DTOs for each layer for each domain model. As I mentioned in other blog posts, you should always think about why you are doing something before you are doing it.
Reasons like “this is the way we have always done it” or “this is the best practice” do not stand up to scrutiny. A dispassionate assessment of an approach should be taken before engaging in a practice. You should also be able to defend your choice in a technical debate without falling back on regurgitated lines like “I’m all about clean code.”

The DTO Pattern is an Anti-Pattern in Most Cases

I used to use DTOs a lot too about 4 or 5 years ago along with the repository pattern. I had been conditioned to never allow your domain models to cross layers and to keep everything separated. I was one of the lemmings following after what everyone had done before me, never thinking about why I was doing it. Automapper was the life blood of the application as I mapped to view models, data models, api models, and so on and so forth. New layer? New set of DTOs! All those duplicated classes, all that mapping, all that suffering and pain wrought upon the application in the name of the holy grail: separation.

Thankfully, my approach evolved over time and I began to question why I was going through all of this. Was it really worth while to incur the cost of extra classes and mapping just so I could say I wasn’t using my domain models with entity framework? How about my API? Should I really be calling everything a DTO? Is half my application calling Automapper really a good practice?

View Models vs DTOs

I don’t consider View Models to be DTOs. View Models can encapsulate logic, validation, or anything else you might include that is specific to the view. Your view model may very well end up with most, if not all of the properties of the domain model that it is built on. More often than not though, the view model only contains what is needed for the view to function. I have, however, seen people use DTOs as their view models. A view model is not a DTO, and you especially don’t need to map from a view model to a DTO and then to a Domain model. When MVC and Razor were still all the rage, it was very common to use automapper to map from a View Model to a Domain Model. This is a perfectly valid approach that still makes sense if you are using Razor. Just as you should not use a DTO for your view, you should not use a domain model either.

Most new applications have a harder separation between the server and the client. The rise of React, Angular, and Vue now removes the old approach of a C# view model that could be directly mapped to a domain model. In addition, the rise of JSON based ASP.NET Web Api and the subsequent decline of WCF have further reduced the need for DTOs.

ASP.NET Web Api and WCF

In the days of WCF, there was a rational argument for the usage of DTOs. You probably didn’t see the DTO suffix on these objects and instead are more familiar with the typical Request and Response suffixes for WCF endpoints. On this note, I want to digress for a moment and discuss the DTO suffix in general: it sucks. It is perhaps the least descriptive suffix ever created. There was a certain fortune 100 that I worked with a number of years ago who decided to suffix all of their WCF requests and responses with “DTO.” Unfortunately these WCF services all worked with the same domain, and they had a lot of them. So what happened when an application ended up using multiple WCF services in the same class? Name collisions everywhere followed by aliasing everything.

At the time I tried to explain the problem with the situation with my Harry Potter example. Imagine if the author of Harry Potter had gotten lazy and decided to name all the characters Harry Potter. She needed a way to differentiate between them though so she prefixed each one with a number. That is essentially what you are doing when you suffix all your DTOs as “DTO.” Writing software is just like writing a book. It needs to be descriptive, and ultimately it needs to tell a story. The solution name is your book title, the projects your volumes, the classes your chapters, and the methods your paragraphs. Reading a book with everyone named HarryPotterDTO is just as annoying as having to read your class that has six different OrderDTOs from six different WCF service proxies.

Web Api is a Medium to Interact With the Domain

This isn’t 2008 anymore though, or even 2010. We are now in the world of micro services driven by JSON based Web APIs that are called by completely client side applications built on modern javascript frameworks. In the case of WCF you had to publish a proxy which would give the client access to whatever properties were in the proxy you published. It was completely reasonable to use separate request/response classes that were then mapped to your domain. That argument doesn’t exist with Web Api. The client is only aware of what you send them, and there are many ways to manage that without resorting to DTOs.

I advocate using your domain classes directly in your API. The reason is that if someone is interacting with your API then they are ultimately interacting with your business and all actions on the API represent that. Using your domain class does not mean that you have to allow all properties to be modifiable. You still have complete control over everything, and in terms of publishing what your API accepts, tools like swagger let you control what parts of the domain are published as your contract. There are a number of different ways to control this including using something like request post processing with ASP.NET filters. The only time I advocate the usage of a DTO is when calling third party APIs or APIs that reside outside of the domain that your application is providing.

What About Persistence Ignorance?

Simply using your domain models as your entities with Entity Framework does not automatically pollute the domain with persistence implementation details. As long as you keep your entity framework configuration and context in a separate assembly, then there is no reason your domain needs to be aware of its existence. As I have discussed before, Entity Framework is already an abstraction of your persistence implementation that provides you a generic repository pattern and a unit of work pattern. I have seen certain blogs advocate that your data model is not your domain model. From a principle standpoint, this is true, but from a practical standpoint having a completely separate list of data models that map to your domain has little gain in today’s world. In the event you have a table that truly has no representation in your domain, then by all means create a DataModel for it. Don’t resort to a DTO suffix and don’t blindly do it for every table. Use DTOs responsibly and you’ll be happier for it.

Sean Leitzinger

Solutions Architect at Edgeside Solutions
.NET and C# aficionado with an interest in architecture, patterns, practices, and more. Microsoft fanatic.

Latest posts by Sean Leitzinger (see all)

2 Replies to “Think Before You Use The DTO Pattern”

  1. If all domain models are fully encapsulated (private setters), and exposed only via constructors and public methods. Now I cannot use my domain models as parameters for post/put end points, right?

    I cannot trust incoming payloads, and asp.net core model binding won’t access private setters, thous would be defeating the purpose anyway!

    So i find myself compelled to use DTOs in this scenario! And am thinking now, if i am accepting DTOs inbound, should i use them outbound (in Get end points)?!

    1. Well, if you went that route then yes you have no choice but to use DTOs in this case. This post wasn’t about how you should never use DTOs, but more about how you should think before you use them. They shouldn’t be some sort of standard knee jerk reaction every time we cross an internal layer. That being said, can’t say I agree with the whole private setters for domain models approach. I can understand it for value objects, but all domain models? To me that feels like a design choice I wouldn’t personally make.

Leave a Reply

Your email address will not be published. Required fields are marked *