I have a single ASP.NET 5.0 (vnext) project where I am implementing both a Web Api and an Mvc front end. I want my Mvc controller to call the Web Api controller, which is working just fine. I built the api based on the example at http://www.asp.net/vnext/overview/aspnet-vnext/create-a-web-api-with-mvc-6, and it is working great. The Mvc front end can call the WebApi controller successfully, but the ITodoRepository doesn't get provided by the dependency injection framework when I instantiate it from the Mvc controller.
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());
}
...
I was able to add an ITodoRepository to the HomeController with the [Activate] attribute, and then pass that to the constructor for the TodoController, but that doesn't pass the smell test to me. Home Controller shouldn't have to have or even know about those.
Is there another way to create the TodoController instance that will invoke the DI logic and provide the dependencies?
Dependency injection into controllers in ASP.NET Core 1 Constructor Injection. Services are added as a constructor parameter, and the runtime resolves the service from the... 2 Action injection with FromServices. 3 Access settings from a controller. Accessing app or configuration settings from within a controller is a common pattern. More ...
A container or an object which creates and passes the dependant object in an application is called Dependency Injection. In simple words instead of creating dependant objects manually by a programmer, objects are get created by library container which normally handles both the creation and garbage handling.
In your Startup.cs can tell the MVC to register all your controllers as services. Then you can simply inject the desired controller in your other controller via the DI mechanism and invoke its action method. Show activity on this post.
Dependency injection is a technique that follows the Dependency Inversion Principle, allowing for applications to be composed of loosely coupled modules. ASP.NET Core has built-in support for dependency injection, which makes applications easier to test and maintain.
If you're concerned about code smell, the main concern should be about having one controller calling another controller.
Controllers are meant to be called in two scenarios:
Instead, I recommend having both controllers call a business logic component that itself might use dependency injection to acquire its dependencies, and that each controller perhaps use dependency injection to acquire the business logic dependency as well.
public class HomeController : Controller {
public HomeController(IMyAppBusinessLogic bll) { ... }
}
public class WebApiController : Controller {
public WebApiController(IMyAppBusinessLogic bll) { ... }
}
public class MyAppBusinessLogic : IMyAppBusinessLogic {
public MyAppBusinessLogic(ITodoRepository repository) { ... }
}
Any middleware registered using app.UseServices
are available only within the scope of a web request. There is no web request context when you are trying to instantiate the webapi controller directly from your MVC app and therefore the dependencies will not be resolved.
It's normal to create an execution context manually for the purposes of unit testing. Not sure which DI framework are you using but I do something like the following in my project (OWIN not vNext) which is using SimpleInjector
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();
}
});
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With