Gilian
Gilian

Reputation: 1599

Dotnet core method injection with controller methods

Lets say i have the following controller in dotnet core:

[Route("api/v1/[controller]")]
public class ValuesController : Controller
{
    private readonly IHandler<ValuesRequest, ValuesResponse> _valueHandler;
    private readonly IHandler<ValuesIdRequest, ValuesIdResponse> _valueIdHandler;

    public ValuesController(IHandler<ValuesRequest, ValuesResponse> valueHandler, 
                            IHandler<ValuesIdRequest, ValuesIdResponse> valueIdHandler)
    {
        _valueHandler = valueHandler;
        _valueIdHandler = valueIdHandler;
    }

    [HttpGet]
    public ValuesResponse Get(ValuesRequest request)
    {
        return _valueHandler.Handle(request);
    }

    [HttpGet("{id}")]
    public ValuesIdResponse Get(ValuesIdRequest request)
    {
        return _valueIdHandler.Handle(request);
    }
}

As you can see in the code above, I'm using dependency injection though the constructor. However, I was thinking on how I could reduce the amount of code. So, I was thinking about using method injection, which should reduce the code to something like this:

[Route("api/v1/[controller]")]
public class ValuesController : Controller
{
    [HttpGet]
    public ValuesResponse Get(ValuesRequest request, IHandler<ValuesRequest, ValuesResponse> handler)
    {
        return handler.Handle(request);
    }

    [HttpGet("{id}")]
    public ValuesIdResponse Get(ValuesIdRequest request, IHandler<ValuesIdRequest, ValuesIdResponse> handler)
    {
        return handler.Handle(request);
    }
}

I was wondering if it is possible to do something like this in combination with controller params. I tried finding an answer on the web, however I could not find similar problem/solution.

Upvotes: 12

Views: 8054

Answers (2)

Nkosi
Nkosi

Reputation: 247008

Reference 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] as shown here:

public ValuesResponse Get(ValuesRequest request, [FromServices]IHandler<ValuesRequest, ValuesResponse> handler)
{
    return handler.Handle(request);
}

Upvotes: 13

alsami
alsami

Reputation: 9815

While the answer would work using [FromService] within your actions, I have another suggestion.

From what I understand by reading the code you have provided is, that you use some kind of CQRS. For that case I can suggest MediatR. You will then only need to inject one interface into your controller and send your request using the IMediator. This way you will keep your controller small and clean and you will not need to inject all the other handlers.

There is a nice and handy extension for Microsoft's IoC-Container to register all your handlers and all other necessary classes to use MediatR.

services.AddMediatR(typeof(Startup).Assembly);

Upvotes: 5

Related Questions