C# 从另一个控制器调用控制器时的依赖项注入

C# 从另一个控制器调用控制器时的依赖项注入,c#,asp.net-mvc,asp.net-web-api,asp.net-core,C#,Asp.net Mvc,Asp.net Web Api,Asp.net Core,我有一个单独的ASP.NET 5.0(vnext)项目,在这个项目中,我同时实现了一个Web Api和一个Mvc前端。我希望我的Mvc控制器调用WebAPI控制器,它工作正常。我基于上的示例构建了api,它工作得非常好。Mvc前端可以成功地调用WebApi控制器,但是当我从Mvc控制器实例化依赖注入框架时,依赖注入框架没有提供ITodoRepository public class Startup { public void Configure(IApplicationBuilder a

我有一个单独的ASP.NET 5.0(vnext)项目,在这个项目中,我同时实现了一个Web Api和一个Mvc前端。我希望我的Mvc控制器调用WebAPI控制器,它工作正常。我基于上的示例构建了api,它工作得非常好。Mvc前端可以成功地调用WebApi控制器,但是当我从Mvc控制器实例化依赖注入框架时,依赖注入框架没有提供ITodoRepository

public class Startup
{
    public void Configure(IApplicationBuilder app, ILoggerFactory logFactory)
    {
        ...
        app.UseServices(services =>
        {
            services.AddSingleton<ITodoRepository, TodoRepository>();
        });
        ...

[Route("api/[controller]")]
public class TodoController : Controller
{
    /* The ITodoRepository gets created and injected, but only when the class is activated by Mvc */
    TodoController(ITodoRepository repository)
    {
        _repository = repository;
    }

    [HttpGet]
    public IEnumerable<TodoItem> Get()
    {
        return _repository.AllItems;
    }
    ...

public class HomeController : Controller
{
    public IActionResult Index()
    {
        var tc = new TodoController(/* have to create my own ITodoRepository here */);
        return View(tc.Get());
    }
    ...
公共类启动
{
公共void配置(IApplicationBuilder应用程序、iLogger工厂日志工厂)
{
...
app.UseServices(服务=>
{
services.AddSingleton();
});
...
[路由(“api/[控制器]”)]
公共类TodoController:控制器
{
/*ITodoRepository被创建和注入,但只有当类被Mvc激活时才被创建和注入*/
TodoController(ITodoRepository存储库)
{
_存储库=存储库;
}
[HttpGet]
公共IEnumerable Get()
{
返回_repository.AllItems;
}
...
公共类HomeController:控制器
{
公共IActionResult索引()
{
var tc=新的TodoController(/*必须在此处创建我自己的ITodoRepository*/);
返回视图(tc.Get());
}
...
我可以使用[Activate]属性向HomeController添加一个ITodoRepository,然后将其传递给TodoController的构造函数,但我没有通过嗅觉测试。Home Controller不应该有,甚至不应该知道这些


是否有其他方法来创建TodoController实例,以调用DI逻辑并提供依赖关系?

使用
app.UseServices
注册的任何中间件仅在web请求的范围内可用。当您试图直接从您处实例化webapi控制器时,没有web请求上下文r MVC应用程序,因此不会解决依赖关系

出于单元测试的目的,手动创建执行上下文是正常的。不确定您使用的是哪个DI框架,但我在使用SimpleInjector的项目(OWIN而不是vNext)中执行了如下操作

public static void UseInjector(this IAppBuilder app, Container container)
{
    // Create an OWIN middleware to create an execution context scope
    app.Use(async (context, next) =>
    {
        using (var scope = container.BeginExecutionContextScope())
        {
            await next.Invoke();
        }
    });            
}

如果您担心代码气味,那么主要的问题应该是让一个控制器调用另一个控制器

public class Startup
{
    public void Configure(IApplicationBuilder app, ILoggerFactory logFactory)
    {
        ...
        app.UseServices(services =>
        {
            services.AddSingleton<ITodoRepository, TodoRepository>();
        });
        ...

[Route("api/[controller]")]
public class TodoController : Controller
{
    /* The ITodoRepository gets created and injected, but only when the class is activated by Mvc */
    TodoController(ITodoRepository repository)
    {
        _repository = repository;
    }

    [HttpGet]
    public IEnumerable<TodoItem> Get()
    {
        return _repository.AllItems;
    }
    ...

public class HomeController : Controller
{
    public IActionResult Index()
    {
        var tc = new TodoController(/* have to create my own ITodoRepository here */);
        return View(tc.Get());
    }
    ...
控制器应在两种情况下调用:

  • 通过系统(即MVC)
  • 通过单元测试
  • 相反,我建议让两个控制器调用一个业务逻辑组件,该组件本身可能使用依赖项注入来获取其依赖项,并且每个控制器可能也使用依赖项注入来获取业务逻辑依赖项

    public class HomeController : Controller {
        public HomeController(IMyAppBusinessLogic bll) { ... }
    }
    
    public class WebApiController : Controller {
        public WebApiController(IMyAppBusinessLogic bll) { ... }
    }
    
    public class MyAppBusinessLogic : IMyAppBusinessLogic {
        public MyAppBusinessLogic(ITodoRepository repository) { ... }
    }
    

    我认为您需要将TodoController作为依赖项注入homecontroller。它应该触发依赖项链的创建。将TodoController作为依赖项添加并在Startup.cs中注册的正确方法是什么?我是否需要制作一个接口ITodoController,然后执行类似services.AddTransient之类的操作?@lordjeb如何从MVC控制器调用webapi方法?webapi上下文必须存在,才能使管道中的中间件正常工作。@su8898我只是试图直接实例化webapi控制器,以避免整个中间件过程。我的webapi控制器返回我需要的对象,所以我想我可以使用c这个问题让我的大脑流血。停止滥用控制器。我正在HomeController.Index()中处理一个web请求。是否有某种方法可以在该上下文中实例化TodoController?对于DI,我只是使用vnext中内置的内容。好主意,但如何实现这一点?如何初始化
    MyAppBusinessLogic