A Data Transfer Object, DTO, is a very simple data-only object typically used for marshalling data across some kind of boundary in your app. A good DTO consists solely of public fields or read/write properties and is Serializable for what should be obvious reasons. Most people seem to gravitate toward read/write properties. I don’t really have an opinion on the matter. While it’s not really important whether or not that boundary lives on another server or AppDomain those are typically the boundaries that require DTOs. WCF calls them DataContracts.
Smart You Say?
I know, “Smart” and “DTO” don’t seem to belong together. Isn’t a DTO just for data transport? Shouldn’t I limit my DTOs to one mission and purpose in life? Yes and no. While you should keep the DTO simple and limited to a single responsibility, I’m a fan of something I’ve been calling a “Smart DTO.” A Smart DTO is a lot like the a Plain Old DTO (PODTO? POD? Nah.) only it adds a few features that the consumer of your DTO can leverage if it wants too. Data Binding and declarative validation are excellent candidates. (Even though I’m using the term Smart DTO you will, I hope, recognize that I’m still keeping things fairly dumb.)
Data Binding
There is a tiny bit of efficiency you can gain by defining a base class that provides the basic infrastructure needed for data binding in .NET. I say tiny because it only saves you from a few lines of code, but, hey, every little bit counts right?
public abstract class SmartDTO : INotifyPropertyChanged { public SmartDTO() {} public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged(string propertyName) { if (this.PropertyChanged != null) { PropertyChangedEventArgs args = new PropertyChangedEventHandler(propertyName); this.PropertyChanged(this, args); } } }
In your DTO subclass you’d consume the functionality of the base class like so:
public class PersonDTO : SmartDTO { private string _name; public PersonDTO() {} public string Name { get { return _name; } set { _name = value; OnPropertyChanged("Name"); } } }
Declarative Validation
Validation is also a convenient thing to put into your Smart DTOs. Specifically I’m talking about the attribute-based implementation of the Martin Fowler’s Notification pattern. I won’t get super specific on this as Jeremy Miller just posted a recipe for implementing this pattern. The DTO above would look like so:
public class PersonDTO : SmartDTO { private string _name; private string _email; public PersonDTO() {} [Required] public virtual string Name { get { return _name; } set { _name = value; OnPropertyChanged("Name"); } }
[Required, EmailFormat] public virtual string Email { get { return _email; } set { _email = value; OnPropertyChanged("Email"); } }
DTO Do’s and Don’ts
DO NOT bother with interfaces for your DTOs.
DO define a SmartDTO base class with infrastructure for data binding.
DO use declarative validation on your DTO classes.
DO put your DTOs in a separate assembly and don’t be afraid to distribute that assembly to the consumer IF you own the consumer.
DO NOT rely on the consumer to validate the contents of a DTO.
DO use virtual properties to facilitate using your DTOs with your favorite mocking framework.
DO consider writing a simple Domain-Specific Language for your DTOs. It’s very easy to do and will save a great deal of typing. A simple code generator with a very simple file format will get you to where you need to go, ex:
Class Namespace
Class Name
Property1:Type:Validator1,Validator2,Validator3
PropertyN:Type:Validator1,Validator2,Validator3MyCompany.MyProduct.DTO
Person
FirstName:string:Required
LastName:string:Required
Ssn:string:Required,SsnFormat
Email:string:Required,EmailFormat
DO NOT confuse the DTO with an Entity (Business Object). Entities model the data and behavior of business constructs that have entities. DTOs model the data of messages. These messages may coincidentally resemble the data modeled in a given Entity.
DO NOT define methods or behaviors on your DTOs. Behavior on a DTO is a good smell that you’re moving expanding past the pattern’s intent and maybe confusing the DTO with the Entities.
DO NOT develop DTOs test-first. In my opinion it’s a complete waste of time and misapplication of the practice. Properly test-driving the design of the Service Layer that consumes/produces the DTOs will ensure they get coverage and the benefit of the test suite safety net.

GitHub
LinkedIn
Twitter