ASP.Net Core Calling a controller from another controller

In my ASP.NET Core MVC 6 solution, I have two sets of controllers. One set contains web pages with their usual forms. Another set contains API controllers.

To avoid duplication of db logic, web controllers use API controllers. I am currently creating an instance of the required controller manually, passing it a DbContext as a constructor argument. This is the DbContext given to the web controller by injecting dependencies.

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

How can I use the dependency injection system built into ASP.Net 5 to instantiate the required API controller for me? Then it will automatically fill in the required constructor parameters.

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

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

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 hope 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);
}
+21
source share
5 answers

, :

  1. Startup.cs ConfigureServices: services.AddTransient <Areas.Api.Controllers.FoobarController, Areas.Api.Controllers.FoobarController>();
  2. , , ctor .

, User Url .

- DI IHttpContextAccessor User IUrlHelper Url:

public class FoobarController : Controller
{
    private readonly ApplicationDbContext _dbContext;
    private readonly IHttpContextAccessor _httpContextAccessor;
    private readonly IUrlHelper _urlHelper;
    public FoobarController(ApplicationDbContext dbContext, IHttpContextAccessor httpContextAccessor, IUrlHelper _urlHelper, [...])
    {
         _dbContext = dbContext;
         _httpContextAccessor = httpContextAccessor;
         _urlHelper = urlHelper;
    }

    public FoobarResponse List(FoobarRequest request)
    {
        var userId = _httpContextAccessor.HttpContext.User.GetUserId();
        var response = new FoobarResponse();
        response.List = _dbContext.Foobars.Where(f => f.UserId == userId).ToList();
        response.Thumb = 
        return response;
    }
}

- :

public class HomeController : Controller
{
    private Areas.Api.Controllers.FoobarController _foobarController;
    public HomeController(Areas.Api.Controllers.FoobarController foobarController)
    {
        _foobarController = foobarController;
    }

    private void InitControllers()
    {
        // We can't set this at Ctor because we don't have our local copy yet
        // Access to Url 
        _foobarController.Url = Url;
        // Access to User
        _foobarController.ActionContext = ActionContext;
        // For more references see https://github.com/aspnet/Mvc/blob/6.0.0-rc1/src/Microsoft.AspNet.Mvc.ViewFeatures/Controller.cs
        // Note: This will change in RC2
    }

    public IActionResult Index()
    {
        InitControllers();

        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);
    }
}

ASP.Net Core MVC6 RC1 . , RC2, , , User Url, .

+9

ASP.Net 5 API?

Startup.cs MVC .

services.AddMvc().AddControllersAsServices();

DI .

+21

. , . HTTP-, API. , , HTTP- -. (, ).

+9

? . DI , ?

:

public class MvcController
{
    SharedComponent sharedComponent;
    public MvcController(SharedComponent sharedComponent)
    {
        this.sharedComponent = sharedComponent;
    }
    public IActionResult Index()
    {
        var model = new IndexViewModel();
        model.Foo = shredComponent.List(new FoobarRequest() { Foo = true, Bar = false });
        model.Bar = shredComponent.List(new FoobarRequest() { Foo = false, Bar = true });
        return View(model);   
    }
}

// API

public class SharedComponent
{
    public SharedComponent(DBContext dbContext, AppEnvironment appEnvironment, UserManager userManager, RoleManager roleManager, 
        EmailSender emailSender, SmsSender smsSender)
    {
       ...Store in fields for later usage
    }
}
0

, . , - ASP.Net , -, , , .

, , :

public interface ICalculator {
    int Add(int left, int right);
}

, -:

public class MyCalculator : ICalculator {
    public int Add(int left, int right) => left + right;
}

, , WPF, ASP.NET WebAPI. :

[ApiController]
[Route("api/{controller}")]
public void CalculatorController : Controller, ICalculator {
    private readonly ICalculator _calculator;

    public CalculatorController(ICalculator calc) => _calculator = calc;

    [Route("Add")]
    public int Add(int left, int right) => _calculator.Add(left, right);
}

, . (, IUserRepository) , , DbContext.

public CalculatorController(ICalculator calculator, IDbContext db) { }

, , . , , . , , , .

. , -. -, , WCF ASP.NET WebAPI.

I personally participated in several projects in which we had to switch from one database technology to another (from SQL Server to CouchDB), and in which our micro-services were supposed to work as resting web-API services instead of Windows services. If you design things this way, these types of projects become relatively trivial compared to how everything is usually composed.

0
source

Source: https://habr.com/ru/post/1625628/


All Articles