i have a simple controller where i am using the interfaec like this ,
public class HomeController : Controller
{
// GET: Home
private IHotelService hotelService;
public HomeController(IHotelService _hotelService)
{
hotelService = _hotelService;
}
}
its working fine, but when i use same thing with API controller like
public class RoomController : BaseApiController
{
private IHotelService hotelService;
public RoomController(IHotelService _hotelService)
{
hotelService = _hotelService;
}
it gives me error
As pointed out here (and in several other answers on SO), you have most likely not registered your DI container with Web API. Web API is a separate framework than MVC and therefore it has a separate configuration, including dependency injection.
So, you need to set
GlobalConfiguration.Configuration.DependencyResolver = MyDependencyResovler(container);
at application startup. The details of how to do this depend on what container you are actually using and whether you use a stock dependency resolver or roll your own as shown in Dependency Injection in ASP.NET Web API 2.
Related
Question mentions it all.
In spring boot I am able to use the AutoWired annotation to automagically inject a dependency into my controller.
class SomeController extends Controller {
#AutoWired
private SomeDependency someDependency;
}
For asp.net-core-mvc I am curious as to if it has this annotation, currently the way to do it is by adding it as an argument to the constructor
[Route("api/[controller]")]
public class SomeController : Controller
{
private SomeContext _someContext;
public SomeController(SomeContext someContext)
{
_someContext = someContext;
}
}
There is no annotation.
You just need to make sure you register the dependency with the DI container at the composition root which is usually Startup.ConfigureServices
public void ConfigureServices(IServiceCollection services) {
//...
services.AddScoped<SomeContext>();
//...
}
If in your case SomeContext is a DbContext derived class then register it as such
var connection = #"some connection string";
services.AddDbContext<SomeContext>(options => options.UseSqlServer(connection));
When resolving the controller the framework will resolve known explicit dependencies and inject them.
Reference Dependency Injection in ASP.NET Core
Reference Dependency injection into controllers
You can use NAutowired,the field injection
Out of the box, Microsoft.Extensions.DependencyInjection doesn't provide property setter injection (only constructor injection). However, you can achieve this by using the Quickwire NuGet package, which does all the necessary plumbing for you. It extends the ASP.NET core built-in dependency injection container to allow service registration using attributes.
To use it, first add these two lines to your ConfigureServices method:
public void ConfigureServices(IServiceCollection services)
{
// Activate controllers using the dependency injection container
services.AddControllers().AddControllersAsServices();
// Detect services declared using the [RegisterService] attribute
services.ScanCurrentAssembly();
// Register other services...
}
Then simply decorate your controller with the [RegisterService] attribute, and decorate any property to autowire with [InjectService]:
[Route("api/[controller]")]
[RegisterService(ServiceLifetime.Transient)]
public class SomeController : Controller
{
[InjectService]
private SomeContext SomeContext { get; init; }
}
Now SomeContext will automagically get injected with the corresponding registered service without having to go through the constructor song and dance.
For more information, you can also check out this table that maps out which Quickwire attribute corresponds to which Spring Boot annotation.
Adding Structuremap MVC 5 to an ASP.NET MVC project. I would like to have a singleton of my database connection per request - my controllers would share the same database connection. I am implementing the repository pattern here and need each controller to have a copy of its respective repository. I know this is possible but I think I'm missing or mis-interpretting something wrong.
I have a controller, "Bag," that needs a "IBagRepo"
public class BagController : Controller
{
private readonly IBagRepo repo;
public BagController(IBagRepo repo)
{
this.repo = repo;
}
// actions
}
My first attempt was hooking the singleton database connection in the ControllerConvention, as I assume its called once
public class ControllerConvention : IRegistrationConvention {
public void Process(Type type, Registry registry) {
if (type.CanBeCastTo<Controller>() && !type.IsAbstract) {
// Tried something like
registry.For(type).Singleton().Is(new ApplicationDbContext()); // this
registry.For(type).LifecycleIs(new UniquePerRequestLifecycle());
}
}
}
But it came clear that this isn't the right file to make this change. I went into the registry class that was automatically generated upon installing the nuget package and tried fiddling around with this.
public class DefaultRegistry : Registry {
#region Constructors and Destructors
public DefaultRegistry() {
Scan(
scan => {
scan.TheCallingAssembly();
scan.WithDefaultConventions();
scan.With(new ControllerConvention());
});
// httpContext is null if I use the line below
// For<IBagRepo>().Use<BagRepo>().Ctor<ApplicationDbContext>().Is(new ApplicationDbContext());
}
#endregion
}
I haven't seen a problem like this out here yet. Am I passing in the right types within my DefaultRegistry class?
What you're wanting is effectively the default behavior if you had been using the StructureMap.MVC5 nuget: https://www.nuget.org/packages/StructureMap.MVC5/. As long as your DbContext is registered with the default lifecycle, that package is using a nested container per http request which effectively scopes a DbContext to an HTTP request for unit of work scoping.
Different tooling than MVC & EF, but I described similar mechanics for FubuMVC + RavenDb w/ StructureMap in this blog post: http://jeremydmiller.com/2014/11/03/transaction-scoping-in-fubumvc-with-ravendb-and-structuremap/
I ended overriding the default controller factory and not using structuremap
I've some api controller that i want to register at runtime in my mvc application.
The controller itself resides into Class Library project and looks like:
public class CustomController : ApiController
{
public string Get()
{
return "Hello";
}
}
I've compile that library (gave it a name Injection.dll), and in my mvc app try to register those controller via Unity.Mvc library container
public static class UnityConfig
{
public static void RegisterComponents()
{
var container = new UnityContainer();
// register all your components with the container here
// it is NOT necessary to register your controllers
// e.g. container.RegisterType<ITestService, TestService>();
Assembly customLogicAssembly = Assembly.LoadFrom(HttpContext.Current.Server.MapPath("~/bin/" + "Injection.dll"));
Type existingType = customLogicAssembly.GetTypes().First();
container.RegisterType(existingType);
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
}
}
So it seems that registration works fine and i have no errors while debuggig it, but
i don't have expected result, when i navigate to api/Custom/Get i have an The resource cannot be found. error in browser.
Pls help what i miss here.
MVC and Web API have each its own dependency resolver.
Your code is registering the MVC Dependeny Resolver:
DependencyResolver.SetResolver(yourResolver);
What you need to register is the Web API Dependency resolver, like this:
GlobalConfiguration.Configuration.DependencyResolver = yourResolver;
The expected resolver in both cases must implement IDependencyResolver, but it serves a different purpose.
It's not recommended that you share the same dependency resolver (thus container and composition root) for both things. If you need to do so, use two different instances of IDependencyResolver and register the controllers where they belong.
IMPORTANT NOTE
There are two different IDependencyResolver interfaces, one for MVC, and the other for Web API. They have the same name, but are on different namespaces. And you need to implement the appropriate for each case (or both, if you need to implement DI for both MVC and Web API):
System.Web.Mvc.IDependencyResolver, for MVC
System.Web.Http.Dependencies.IDependencyResolver, for Web API
I have an ApiController in an Area of my MVC website, I'm injecting dependencies into it via Unity and my controllers extend the System.Web.Http.ApiController.
I'm using Unity from Microsoft.Practices.Unity.dll, v3.0.0.0.
I can route to the controller with the following in ApiAreaRegistration
context.MapRoute(
"Api_default",
"Api/users/{action}/{id}"
);
But I get the following error :
Type 'Project.Areas.Api.Controllers.UsersController' does not have a default constructor
However if I add a default constructor my dependencies don't get resolved.
I'm beginning to feel like I'm missing something structural?
You don't show your controller registration and the error message suggests you have not registered the controller dependencies.
I use the Unity.WebAPI NuGet package to take care of the controller build-up and container lifetime management. If your project also uses MVC controllers the Unity.Mvc3 will handle those controllers. These packages get Unity wired-up for my controllers with very little code.
My Unity bootstrap looks like this
public static class UnityConfig
{
var container = BuildUnityContainer();
// MVC controllers
DependencyResolver.SetResolver(new Unity.Mvc3.UnityDependencyResolver(container));
// WebAPI controllers
GlobalConfiguration.Configuration.DependencyResolver = new Unity.WebApi.UnityDependencyResolver(container);
}
private static IUnityContainer BuildUnityContainer()
{
var container = new UnityContainer();
// register all your components with the container here
// you don't need to register controllers
container.RegisterType<IUsersService, UsersService>();
...
return container;
}
And I don't worry about my controller creation -- It just works.
public class UsersController : ApiController
{
private IUsersService service;
public UsersController(IUsersService service)
{
this.service = service;
}
...
}
GlobalConfiguration.Configuration.DependencyResolver =
new UnityDependencyResolver(YOUR_UNITY_CONTAINER);
and from http://msdn.microsoft.com/en-us/library/dn178463(v=pandp.30).aspx#sec18 you can find that you should search for 'Unity bootstrapper for ASP.NET WebApi' and you get the UnityDependencyResolver from the namespace: 'Microsoft.Practices.Unity.WebApi'.
Easiest way is just to install the WebApi Bootstrapper and look in the App_Start folder.
I have an MVC4 site using Castle Windsor that I want to add some WebAPI calls to, so I start digging around a little bit on the interwebs.
Now I don't know the ins and outs of IoC; I followed a tutorial for how to set up Castle Windsor on my project, injecting the IUnitOfWorkFactory and the IApplicationService as public properties in a base controller, and a few other interfaces as needed in the controller constructors. It works swimmingly, so I've never had to do more with it.
Everywhere that I'm reading up on WebAPI, I'm told DI will not work so well using Castle Windsor, talking about problems with the IDependencyResolver and IDependencyScope. There are several workarounds and implementations of how to get around this problem, but what is not clear to me is what exactly the problem is. Code snippets are included, but the assumption is you know what class they belong to, and how they are invoked, which unfortunately I do not. Additionally, all the examples I've seen online refer to an exclusive WebAPI project, and not an MVC4 project with a couple ApiControllers judiciously tossed in. I don't know how, or if, this affects anything.
Why won't what I have working with my standard controllers not work with an API controller? What kind of code acrobatics need to do to get WebAPI calls and standard web calls to work in the same application?
Existing Castle Windsor MVC configuration
Assuming you have MVC and Castle Windsor setup similarly to the Castle Windsor MVC tutorial, adding IoC to get Web API controllers to utilize dependency injection is very simple with Mark Seemann's post (note that he explains why not to use IDependencyResolver).
From the Castle Windsor tutorial you should have something like this in Global.asax.cs.
private static IWindsorContainer container;
protected void Application_Start()
{
//... MVC / Web API routing etc.
BootStrapper bs = new BootStrapper();
container = bs.ConfigureCastleWindsorMVC();
}
BootStrapper.ConfigureCastleWindsorMVC() snip
IWindsorContainer container = new WindsorContainer()
.Install(
new LoggerInstaller()
//...,
, new ControllersInstaller()
);
var controllerFactory = new WindsorControllerFactory(container.Kernel);
ControllerBuilder.Current.SetControllerFactory(controllerFactory);
return container;
Required changes
From Mark Seemann's post you need to get into Web API's entry point (Composition Root) through the IHttpControllerActivator. Here's his adapter implementation which you need.
public class WindsorCompositionRoot : IHttpControllerActivator
{
private readonly IWindsorContainer container;
public WindsorCompositionRoot(IWindsorContainer container)
{
this.container = container;
}
public IHttpController Create(HttpRequestMessage request,
HttpControllerDescriptor controllerDescriptor, Type controllerType)
{
var controller =
(IHttpController)this.container.Resolve(controllerType);
request.RegisterForDispose(
new Release(() => this.container.Release(controller)));
return controller;
}
private class Release : IDisposable
{
private readonly Action release;
public Release(Action release) { this.release = release; }
public void Dispose()
{
this.release();
}
}
}
With the IHttpControllerActivator adapter and the MVC Castle Windsor container implementation, you just need to configure it in the Global.asax.cs (or in BootStrapper if you used that). It has to be after the MVC initialization since the MVC initialization has all of the installers.
private static IWindsorContainer container;
protected void Application_Start()
{
// MVC / Web API routing etc.
BootStrapper bs = new BootStrapper();
container = bs.ConfigureCastleWindsorMVC();
// Web API Castle Windsor ++ ADD THIS ++
GlobalConfiguration.Configuration.Services.Replace(
typeof(IHttpControllerActivator),
new WindsorCompositionRoot(container));
}
Final Result:
The Web API controllers can use your injected dependencies the same as your MVC controllers.
public class TestController : ApiController
{
private readonly ITestService TestService;
public TestController(ITestService testService)
{
this.TestService = testService;
}
// GET api/<controller>
public IEnumerable<string> Get()
{
return TestService.GetSomething();
//return new string[] { "value1", "value2" };
}
}
In order to use Windsor with webapi follow
http://blog.ploeh.dk/2012/10/03/DependencyInjectioninASP.NETWebAPIwithCastleWindsor/
(BEH: fixed link)
Read also
Castle Windsor/DelegatingHandler/IPrincipal Dependency Injection (DI)/Inversion of Control (IoC) in ASP.NET Web API
You can use webapi and MVC controllers in the same app (I prefer to keep it separate) but routing and controllers factory are different and you have to set up two different configuration and handle routing overlaps...
For MVC & Windsor you can find a great
The following sample project gave me the answer I was looking for. It uses Castle Windsor for dependency injection. I was able to use MVC Controllers alongside Web API controllers on the same Application.
mirajavora / WebAPISample
Here's the post detailing it:
Getting Started with ASP.NET Web API
First as Iko stated you need to create a class that implements IHttpControllerActivator.
Then in ContainerBootstrapper in Bootstrap() add the following Replace the default with the one implemented:
//This will help in creating Web api with Dependency injection
GlobalConfiguration.Configuration.Services.Replace(
typeof(IHttpControllerActivator),
new WindsorCompositionRoot(container));
Lastly which is not mentioned here and it didn't work for me without it that you should add the following in you implemented IWindsorInstaller service inside install() :
container.Register(
Classes.FromThisAssembly()
.BasedOn<ApiController>()
.LifestyleTransient()
);