13

If I had to create some sort of API with a MVC architechture, I would have to decide a naming convention for DTOs that the controller receive and those DTOs that the controller produces I'm right?

For example, given the following code:

public class InStudentDTO
{
    public int Id { get; set; }
    public List<int> Grades { get; set; }
}

public class OutStudentDTO
{
    public int Id { get; set; }
    public bool HasApprovedCourse { get; set; }
}

[HttpPost]
public OutStudentDto StudentHasApprovedCourse(InStudentDto dto)
{
    OutStudentDto outStudentDto = _someService.CalculateStudentApprovedCourse(dto);
    return outStudentDto;
}

This is just a silly example, but the point is that I want to perform some calculation inside a service with the property List<int> Grades and not showing it later on the output of the controller. Thus, as far as I understand I should create a brand new DTO only that doesn't expose the List<int> Grades property, right? If so, how is the right naming convention to this "produced DTOs¨? or should just name those as Viewmodels?

Thanks!

Rod Ramírez
  • 1,138
  • 11
  • 22
  • 2
    Why does your `GET` action have a DTO? GET actions should only have scalar parameters, not complex-types or objects. Otherwise make it a POST action. – Dai Jul 31 '20 at 01:54
  • Hey Dai! Great catch! but as I clarify next.. _This is just a silly example_ not the point of the question – Rod Ramírez Jul 31 '20 at 01:55
  • @Dai Fully opinionated approach. There are some design models that suggest that (GET) parameters are just “DTO fields”. – user2864740 Jul 31 '20 at 01:56
  • @user2864740 Yes, I am voting to close this because it's opinion-based, but that doesn't mean the question isn't worthy of an answer. Questions like these (which can be answered objectively, when the answer is suitably framed) **should** be allowed on StackOverflow. – Dai Jul 31 '20 at 01:57
  • I was mostly referring to “..should only have scalars parameters..”. I guess that was a comment and not an answer. – user2864740 Jul 31 '20 at 01:58
  • @user2864740 A GET request cannot have a request body (strictly speaking HTTP allows for GET-with-body, but it's an edge-case many platforms don't support), so parameters have to be passed-in the resource-path or the querystring, which limits you to scalar values -that's not an opinion, that's an objective-fact. ASP.NET MVC does let you do model-binding from scalar-parameters to a DTO object, but that's almost always a bad idea. It doesn't help things at all. – Dai Jul 31 '20 at 02:00
  • A “DTO” says nothing about needing a request body. So such is not relevant justification between GET or POST usages. It’s just one form for a modeling to map “transferable data”, just as flat parameters are. – user2864740 Jul 31 '20 at 02:01
  • @user2864740 ASP.NET Web API *by default* binds request-bodies to DTO classes - it doesn't bind querystring parameters to DTO classes, only scalars. It's intentionally difficult to model-bind a body-less request to a DTO. – Dai Jul 31 '20 at 02:02
  • @user2864740 I am not talking about response DTOs at all, (only request DTOs) and the context is ASP.NET Web API over HTTP. My comments do not apply to DTOs in other contexts, like gRPC, Protobufs, or DTOs on-disk. – Dai Jul 31 '20 at 02:03
  • 2
    Thanks for your insight guys! I liked the Request/Response approach. I decided to create this question on SO because I couldnt find some valuable resource that distinguish request/response DTOs, they always talk about naming DTOs as {Entity}DTO and it seams odd to me that they had not differenciate them between requested and responded. – Rod Ramírez Jul 31 '20 at 02:03
  • 1
    @RodrigoRamírez That's because it's common to reuse the same DTO type for both requests _and_ responses, especially if it represents a domain-entity / business-object (e.g. a Product, an Order, an Invoice, etc). C# and .NET doesn't support mixins or algebraic-types so it's cumbersome to define one-off types by combining existing types - other languages (like TypeScript) don't have this problem so they have their own way of working with DTOs. – Dai Jul 31 '20 at 02:08
  • Alternatively you can put http method to the Dto name like `StudentGetResponse`, `StudentPutRequest`, ` or `StudentPostRequest` and `StudentPostResponse`. It's very easy to know then for example in testing when to use what object and what properties to fill or expect. – Muflix Oct 11 '22 at 17:50

1 Answers1

17

There is no single standard or naming convention for naming DTO types because it's an implementation concern - I'm not aware of the ASP.NET Web API team endorsing any particular convention either (there's also plenty of bad examples of using actual Entity Framework entity-types as DTOs in the official ASP.NET documentation (DON'T DO THAT for many reasons - unless you know what you're doing)).

However, I have noticed a general trend in the .NET developer community that "In" DTOs (as you call them) are often named ${ResourceName}Request and "out" output/response DTOs are often named ${Resource/Action}Response - it's also not uncommon to have "Dto" as a type-name suffix.

However, when it comes to naming-conventions and coding-style it's generally more important to be consistent than it is to be "correct" - so if your existing project uses Dto as a suffix then do that, but if your project doesn't use a suffix then don't start using one (without a good reason).

Also, avoid ambiguous names like Id - use the full name (StudentId) instead.

In my subjective opinion, given your example, I would name them like so:

public class StudentCourseApprovalRequestDto
{
    public int       StudentId { get; set; }
    public List<int> Grades    { get; set; }
}

public class StudentCourseApprovalResponseDto
{
    public int  StudentId         { get; set; }
    public bool HasApprovedCourse { get; set; }
}

[HttpGet]
public StudentCourseApprovalResponseDto StudentHasApprovedCourse( StudentCourseApprovalRequestDto req )
{
    StudentCourseApprovalResponseDto resp  = _someService.CalculateStudentApprovedCourse( req );
    return resp;
}
Dai
  • 141,631
  • 28
  • 261
  • 374
  • Hi, did you have some sources for this trend? – live2 Mar 11 '21 at 13:50
  • @live2 Please read my answer thoroughly. – Dai Mar 12 '21 at 00:46
  • @Dai "I have noticed a general trend" is not a source. They were clearly asking if you could point to any concrete posts/repos/files that implement this trend you reference to. If not, then that's fine, the answer is no. You don't need to be obnoxious about it. – Dotl Mar 23 '22 at 09:59