When developing controllers in ASP.NET Core, there are certain practices that should be avoided to ensure maintainability, performance, and adheren...
For further actions, you may consider blocking this person and/or reporting abuse
Hey bro, what do you think about this proposal for first point?
Why?
Because, Imagine that your product controller has 5 or more methods implemented, and that each of them requires services such as dependencies...
Then, you will be injecting to the controller constructor an unnecessary amount of service instances that are not going to be used, which increases the memory consumption unnecessarily.
For a small workload you may not notice the difference, but for high workloads, your service will scale faster unnecessarily, so it is better to use the
IServiceProvider
to resolve the instances in the context where they will be used.In effect, you indirectly increase the response speed of your services by not having to resolve and inject unnecessary instances.
Leave your appreciations.
Good vives!!
Hi, thanks for you comment,
Really good point.
I personally like to inject the specific interfaces instead of IServiceProvider for small workloads.
But at the end of the day it depends on the problem we are trying to solve, complexity and the choose architecture.
About your point "product controller has 5 or more methods implemented, and that each of them requires services such as dependencies...
Then, you will be injecting to the controller constructor an unnecessary amount of service instances that are not going to be used, which increases the memory consumption unnecessarily."
For high workloads or scalable services, in 90% of the case I will think about using CQRS, Command/Query separation so our controllers delegate the responsibility to commands or queries to do the actual work (another component)
Just an example...
Apreciate your feadback
Andy, that is a good way and very common strategy in DotNet environment, so, if your mediator is something like the next, so, the unnecessary service instances problem, will not be presented, example:
But is your mediator receive for constructor a lot of Types, it can be a future problem in high workloads.
Personal appreciation:
Lately I am avoiding using Mediator pattern to handle the requests inside the controller, instead, I'm using directly the use case, this makes it simple and I should avoid extra code delegating all the application and domain responsibility to the use case, for example:
Let me know your appreciations, they will be of value for me!! :)
By injecting
IServiceProvider
you are falling into the Service Provider anit-pattern. This is particularly palpable when you examine the constructor signature that you have no idea what actual services are needed for the class to operate.This is particularly troublesome for unit testing. What services should I mock to test the class? All I see is
IServiceProvider
. This is generally a bad idea.The best approach would be to try to separate the concerns as much as possible from the get-go and to try to implement singleton services for the ones that may consume more RAM.
José on that point you are very right, however if
we have had good practices in development
no matter if your architecture is MVC, Clean, Onion, N-Layers, among others, and within those good practices was the fact ofnot having added logic in your controller
, then I assure you that you will not have any problem, because your unit tests would be focused around your Services, UseCases, Commands and Queries units, and you would not have to worry about your controller because you do not have to test anything in it, since it is simply a primary connector between your server and your application layer.Let me know your appreciation after this.
Good vives!!
I still disagree. For example, one can easily write a unit test that makes sure all controllers can be instantiated by using a little reflection. If the controllers' only requirement is
IServiceProvider
, then the unit test achieves nothing.It is best, as you were told by the author, to section the controller into smaller controllers. One way of doing this, as you were told, is to separate the CRUD operations into different controllers.
I don't think you can pose a scenario where I (or others) could not offer a better counter approach.
José, your point is respectable, however I do not see the need to do a unit test on a controller that should not have any logic beyond being a bridge between the Infra layer and the application layer.
I don't understand what value adds a test of those that you mention since the API is going to load everything that extends from BaseController, but respectable.
I withdraw from the crossing of ideas (debate).
¡Good week!
Number 4 is not really a background worker. By using
await
you merely release the threadpool thread. That's it. A background worker is a completely different thing, usually implemented as a class that derives fromBackgroundService
.What is correct is the general statement: Long-running operations should be offloaded to a background worker. The correct way of doing it would be to accept the data, queue the work and return HTTP 202 ACCEPTED along with a transaction identifier for the user to check on the status/progress of the operation.
Number 5 collides with number 2: The fact that Microsoft has provided
ModelState.IsValid
, doesn't mean that it must be used. I actually recommend avoiding it altogether because it violates number 2: You are providing business validation logic in the controller, and the controller's only concern should be to translate data from and to the HTTP protocol. A simple test that demonstrates the violation: Imagine that you are asked to create a command-line tool that runs the business code. If you remove the HTTP layer, you lose the validation logic, which should not happen at all.All in all, thanks for sharing. I wish my co-workers had followed a guide like this 3 years ago. That way I wouldn't have to deal with so many bad things at work.
Hi Jose, thanks for your comment.
Agree with all.
Reading it now again, my example for number 4 was not the best one. But you got the idea... in real world I would go for queues
Thanks again
Thank you :-)
Good points here, thanks for wrote it !
The main point of this, in my view was the Exception Filter Middleware !