
Often seen, often used incorrectly: DTOs. Data Transfer Objects.
In principle, DTO is an umbrella term, a design pattern that is used to transfer data between. In reality, however, the umbrella term is used directly as an implementation, which has disadvantages in all cases.
DTO in ASP.NET Core
Let’s take an ASP.NET Core API as an example in which a user object is to be transferred.
1/// Don't do this!
2public class UserDTO
3{
4 public int UserId { get; set; }
5 public string UserName { get; set; }
6}
Looks like a legitimate object in principle - but for what?
As a response object, this structure makes sense - because I only have necessary properties and values that are directly assigned to the user and must exist.
However, if I were to use this structure for a create flow, i.e. an endpoint that is to create a user, then it makes no sense: because the caller should certainly not set an ID; the application (logic) is responsible for this.
In APIs in particular, it is very often the case that request and response models are structured very differently.
1/// Do this!
2public class UserCreateRequestModel
3{
4 public string UserName { get; set; }
5}
6
7public class UserModel
8{
9 public int UserId { get; set; }
10 public string UserName { get; set; }
11}
12
13// or if you have a special model for the create response
14public class UserCreateResponseModel
15{
16 public int UserId { get; set; }
17 public string UserName { get; set; }
18}
Summary: every API should have separate Request- and Response-Models.
Validation
Another major advantage of this separation is that each model can be structured and set up separately and the validation - e.g. using FluentValidation - can also be set up individually.
This makes implementation much easier, especially in medium-sized and large applications.
DTOs when reading and writing files
As with APIs, models are often used for files to read and write files or to work with the runtime object. However, while APIs should have separate models for requests and responses, this almost never makes sense for files - you only have one structure representation.
But here too, there is no need for the designation “DTO” to be part of the name - after all, you only want to enable the data to be displayed.
1/// Don't do this!
2public class MySettingsDTO
3{
4 public string Field1 { get; set; }
5 public string Field2 { get; set; }
6 public MySubSettingDTO[] SubSettings1 { get; set; }
7}
8
9/// Do this!
10public class ApplicationSettings
11{
12 public string Field1 { get; set; }
13 public string Field2 { get; set; }
14 public MySubSetting[] SubSettings1 { get; set; }
15}
Conclusion
In principle, all models for data transfer can be assigned to the DTO pattern - but you will not see “DTO” as part of the software design name.
It is particularly important that models are given precise names that make it clear what they are used for and that incorrect naming habits do not create a design flaw that is difficult to correct.
Related articles

Mar 17, 2026 · 15 min read
GitHub Copilot - Custom Agents for Full-Stack Teams: A Practical Operating Model for .NET, React and Azure
GitHub Copilot custom agents allow teams to define specialized AI assistants, each with its own role, tool access and behavioral boundaries. …

Mar 10, 2026 · 15 min read
.NET NuGet Trusted Publishing with GitHub Actions
Publishing NuGet packages has traditionally required one uncomfortable compromise: a long-lived API key had to exist somewhere in the …

Mar 09, 2026 · 7 min read
C# 15 Unions: Unions are finally in .NET
After many years of workarounds, design discussions and library-level substitutes, unions are finally becoming a first-class part of C#. The …
Let's Work Together
Looking for an experienced Platform Architect or Engineer for your next project? Whether it's cloud migration, platform modernization or building new solutions from scratch - I'm here to help you succeed.

Comments