6

I have a Controller in ASP Core MVC. I'm trying to trim down the dependency injected services in the constructor so I can start building unit tests more easily. However, I have some services being injected that are only used in one or two controller actions. For example, I inject ILocationService because in a couple of my actions, I need to lookup a country Id number and get a ISO Alpha-2 country code using a database (eg mapping ID number 1 to "CA", mapping 2 to "US", etc.)

Asp Core supports the [FromServices] attribute, so I have the option to inject ILocationService directly into two of my actions instead of injecting them in the controller constructor. The advantage for this is I don't need to always mock/inject ILocationService into my controller from every unit test and its more clear when writing unit tests which services each function depends on.

The obvious disadvantage is now its not completely obvious and clear what services my controller depends on since they are not all grouped in the constructor.

Is using [FromServices] bad practice or a strong indication of code smell?

2 Answers 2

10

This isn't a code smell or bad design at all. In fact, this is precisely why the [FromServices] attribute was created:

Action Injection with FromServices

Sometimes you don't need a service for more than one action within your controller. In this case, it may make sense to inject the service as a parameter to the action method. This is done by marking the parameter with the attribute [FromServices]...

Source: Dependency injection into controllers in ASP.NET Core (emphasis, mine).

More specifically, the [FromServices] attribute enables a form of dependency injection called method injection. Method injection is useful in cases were a dependency is only needed for a single method, or a small enough number of methods it just doesn't make sense to add the dependency as a constructor parameter.

The advantage for this is I don't need to always mock/inject ILocationService into my controller from every unit test and its more clear when writing unit tests which services each function depends on.

The advantage you mention is precisely why you would choose method injection over constructor or setter injection. The [FromServices] attribute itself is just a marker used by the framework so it knows the method parameter should come from the DI container, rather than something mapped from data in the request.

2
  • 3
    Hmm I'm not totally convinced. Just because something exists in a framework does not automatically mean its good practice to use in my opinion. I can think of a few other features that ASPCore supports, but are a strong indication of bad design/code smell in my opinion
    – Brad
    Commented Feb 13, 2019 at 17:16
  • 1
    @Brad: I came back to this answer after a few years and added to it. Does that help clarify the use case for the [FromServices] attribute? Commented Jun 30, 2022 at 19:34
0

Unfortunately [FromServices] on controller actions forces you to make any injected types you use public, as controller actions must be public. Which is a shame as it's otherwise a great feature.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.