Asp.net-core – ASP.Net Core Call a controller from another controller

asp.net-coredependency-injection

In my ASP.Net Core MVC 6 solution I have two sets of controllers. One set contains the webpages with their regular views. Another set contains the API controllers.

To avoid duplicating db logic the web controllers are using the API controllers. Currently I am creating an instance of the required controller manually by handing it a DbContext as constructor argument. This is the DbContext given to web controller by dependency injection.

But whenever I add another constructor parameter to the API controller I need to modify all web controllers that use this API controller.

How can I use the dependency injection system builtin to ASP.Net 5 to create an instance of the required API controller for me? Then it would fill in the required constructor parameters automatically.

One solution could be to move the db logic from the API controllers to a separate layer and call that from both API and web controllers. This would not solve my problem since the new layer would still need the same parameters and I'm not fan of the unnecessary wiring.

Another solution would be to have the web controllers access the API through a web call, but that just adds complexity to the app.

Today I am doing this:

public IActionResult Index()
{
    using (var foobarController = new Areas.Api.Controllers.FoobarController(
        // All of these has to be in the constructor of this controller so they can be passed on to the ctor of api controller
        _dbContext, _appEnvironment, 
        _userManager, _roleManager, 
        _emailSender, _smsSender))
    {
        var model = new IndexViewModel();
        model.Foo = foobarController.List(new FoobarRequest() { Foo = true, Bar = false });
        model.Bar = foobarController.List(new FoobarRequest() { Foo = false, Bar = true });
        return View(model);
    }
}

And I am hoping for something like this:
(This example does not work.)

using (var foobarController = CallContextServiceLocator.Locator.ServiceProvider.GetService<Areas.Api.Controllers.FoobarController>())
{
    var model = new IndexViewModel();
    model.Foo = foobarController.List(new FoobarRequest() { Foo = true, Bar = false });
    model.Bar = foobarController.List(new FoobarRequest() { Foo = false, Bar = true });
    return View(model);
}

Best Answer

How can I use the dependency injection system builtin to ASP.Net 5 to create an instance of the required API controller for me?

In your Startup.cs can tell the MVC to register all your controllers as services.

services.AddMvc().AddControllersAsServices();

Then you can simply inject the desired controller in your other controller via the DI mechanism and invoke its action method.