C
C#2y ago
bookuha

Controllers purpose

I have an entity Book, so far I seen examples where Controllers implement only simple CRUD operations, they get BookDTO, map it to the Book and update entirely. The question is, if I want to do some specific logic on the book, like add another author, what should I do? Another method in controller with a specific route that only receives string and populates it to authors collection in Book object by use of service? Or should I only have these CRUD methods and update it only entirely with this DTO I get from my client (sound very bad for me) Also, do I map DTOs to Entities in controllers and pass entities to services? Or do I make services work with DTOs (also sounds bad to me)
6 Replies
Pobiega
Pobiega2y ago
Most people agree that controllers are primarily for handling HTTP concerns So you would take in a DTO to a controller method that represents some intent, and send to the correct service/handler whatever, then return the correct HTTP response (was there an error? does the user have access to the requested resource?) for example, this is a controller action how I like them.
[HttpGet]
public async Task<ActionResult<TodoListDto>> Get(int id)
{
var query = new GetTodoListQuery()
{
Id = id
};

var result = await _mediator.Send(query);
if (!result.IsSuccess)
{
return result.Error switch
{
NotFoundError notFoundError => NotFound(notFoundError.Message),
ValidationError validationError => BadRequest(validationError.ValidationFailures),
_ => Problem(detail: result.Error.Message, title: "Internal Server Error", statusCode: 500)
};
}

// handle success

// never return the entity directly, so map it.
return _mapper.Map<TodoListDto>(result.Entity);
}
[HttpGet]
public async Task<ActionResult<TodoListDto>> Get(int id)
{
var query = new GetTodoListQuery()
{
Id = id
};

var result = await _mediator.Send(query);
if (!result.IsSuccess)
{
return result.Error switch
{
NotFoundError notFoundError => NotFound(notFoundError.Message),
ValidationError validationError => BadRequest(validationError.ValidationFailures),
_ => Problem(detail: result.Error.Message, title: "Internal Server Error", statusCode: 500)
};
}

// handle success

// never return the entity directly, so map it.
return _mapper.Map<TodoListDto>(result.Entity);
}
bookuha
bookuha2y ago
So I can only have Get, Create, Update, Put, Patch? Would it be inappropriate if I had another method "UpdateDescription" or "UpdateName"?
Pobiega
Pobiega2y ago
Not really. It all depends on if you want to follow REST or not., UpdateDescription wouldn't be very RESTful, but thats only a problem if you explicitly are trying to make a REST api. If you just want a webapi that uses JSON, you can do whatever you feel like What I was trying to get across is that the controller should only care about HTTP stuff, and making sure the right method gets called to handle the request. In my case, thats the mediator handling the query
bookuha
bookuha2y ago
What solution does REST provide to this kind of problem? If I only need to have my description updated. Thank you, I haven't tried mediator yet
Pobiega
Pobiega2y ago
REST is a design philosophy it boils down to that your API should respect the HTTP verbs and "browsable" routes like, if you have a list of fruit, it would be at GET api/fruit a list of fruits and details about a given fruit would be at GET api/fruit/55 etc for updating the description, you'd use PUT api/fruit/55 to "replace" the entire fruit object, according to pure REST but you could just do PUT api/fruit/55/description I guess, but that would bloat your API imho
bookuha
bookuha2y ago
thank you
Want results from more Discord servers?
Add your server
More Posts