Simple Injector Unable to Inject Dependencies in Web API Controllers

Simple Injector unable to inject dependencies in Web API controllers

TLTR: the problem is caused by the implicit way Web API handles resolving controller types; register your Web API controllers explicitly and you'll see where the problem is.

Here is a step by step what is happening under the covers:

  1. The System.Web.Http.DefaultHttpControllerActivator calls into the SimpleInjectorWebApiDependencyResolver and requests the creation of an API controller.
  2. SimpleInjectorWebApiDependencyResolver forwards that call to the SimpleInjector.Container instance.
  3. That Container instance however, does not have any explicit registrations for that API Controller (since you supplied an empty container to the resolver).
  4. Since there is no explicit registration, the container tries to do a last minute registration for that type.
  5. That Controller type however depends on interfaces that can't be resolved because they are not registered in the container (remember, your container is empty).
  6. Although the container would normally throw an exception, null is returned in this case, because the type is requested through the IServiceProvider.GetService method and the type was not registered explictly.
  7. The SimpleInjectorWebApiDependencyResolver's GetService method will return null as well, since it's by definition that it should return null; It should return null when no registration exists (which currently is the case).
  8. Since the DependencyResolver returned null, DefaultHttpControllerActivator will fall back to its default behavior, which means creating that type itself, but this requires the controller to have a default constructor.

Long story short, the problem is caused by the implicit way Web API handles resolving controller types.

So the solution here is to:

  1. Have only one single Container in your web application. This prevents all sorts of trouble and complication of your configuration.
  2. Register all Web API Controllers explicitly in the container. Registering controllers explicitly will ensure that Simple Injector will throw an exception when a controller can't be resolved. Besides, this allows you to call container.Verify() which will make the application fail during startup when the configuration is invalid (a verifiable configuration is important). And this also allows you to diagnose the configuration which gives you even more confidence about the correctness of your configuration.

My advice is to place MVC and Web API in their own project. This will make things much easier.

Registering all Web API controllers can be done with the following code:

container.RegisterWebApiControllers(GlobalConfiguration.Configuration);

UPDATE:

Because this error is so common, newer versions of the SimpleInjectorWebApiDependencyResolver class will simply never return null when a controller type is requested. Instead it will throw a descriptive error. Because of this you should never see error anymore, as long as you use the official SimpleInjectorWebApiDependencyResolver.

SimpleInjector: Injection does not work with MVC 4 ASP.NET Web API

From the stack trace I can see that you are using the new .NET 4.5 ASP.NET Web API and Simple Injector is not in the presented call graph. This probably means that you haven't configured the Simple Injector for use with the new Web API, which is a different registration than what you need for MVC (for some strange reason, and I sincerely hope they fix this in the final release). Since you didn't register a Simple Injector specific System.Web.Http.Dependencies.IDependencyResolver implementation to the Web API's GlobalConfiguration.Configuration.DependencyResolver, you'll get the default behavior, which will only work with default constructors.

Take a look at this Stackoverflow answer Does Simple Injector supports MVC 4 ASP.NET Web API? to see how to configure Simple Injector with the new ASP.NET Web API.

UPDATE

Note that you can get this exception even if you configured the DependencyResolver correctly, but when you didn't register register your Web API Controllers explicitly. This is caused by the way Web API is designed.

Always register your Controllers explicitly.

Parameter not registered when using Simple Injector to inject into an web api Controller Constructor

I never used Simple Injector before, but the IoC patterns is always the same. So as Steven says, you should register IChurchService in the container, so the Framework knows whats the Instance type to inject when demanded.

private static void InitializeContainer(Container container)
{
// For instance:
container.Register(typeof(IRepository<>), typeof(EFRepository<>));
//Adding this should resolve it
container.Register(typeof(IChurchService), typeof(ChurchService));
}

If ChurchService has any dependencies make sure to register those as well. Register all dependencies needed to complete the object graph

Resolve dependencies in ASP.NET Web API with Simple Injector and IHttpControllerActivator

Yes, your implementation is valid.

Only be careful not to use both the SimpleInjectorWebApiDependencyResolver and the SimpleInjectorControllerActivator in the same application. Both start an ExecutionContextScope which could lead to having two scopes within the same web request, so they are mutually exclusive.

A general advantage of using a controller activator over the dependency resolver is that the dependency resolver contract forces the adapter to return null when a service can't be created. This is a very common problem that developers run into, and it often causes the confusing controller does not have a default constructor exception. This problem does not exist when using an IHttpControllerActivator, since the contract forces you to return a value or throw an exception.

The Simple Injector Web API integration project however, prevents this problem with dependency resolver, by never returning null (but throwing an exception instead) in case the requested service is an API controller (and thereby implicitly breaking the IDependencyResolver's contract).

An advantage of using the SimpleInjectorDependencyResolver is that it becomes easier to create message handlers that operate within the execution context scope, since you can trigger the creation of this scope by calling request.GetDependencyScope() method. With the current implementation, the scope just gets started at the time that the controller gets created, which is after you run the handlers. Changing this isn't that hard, but involves changing your controller activator and have an outermost handler that starts the execution context scope (or again falling back on a dependency resolver that manages the execution context scope).

One of the arguments of Mark Seemann is that it becomes hard to pass context around, which is a very valid point, as long as your components don't require this context during construction. But this is not a problem you'll experience when using Simple Injector, because there is an extension method that helps you with accessing the HttpRequestMessage. So although the IDependencyResolver abstraction isn't designed for getting the contextual information, there are ways to get this contextual information.

In the past we decided to go with an adapter for the IDependencyResolver, mainly because this was the common practice with all DI containers. I partly regret this decision, but using the SimpleInjectorDependencyResolver is now usually the easiest way of plugging in Simple Injector into Web API. We considered adding a SimpleInjectorControllerActivator as well, but this had no practical benefit for most users, while we still would had to document when to use what. So we decided to stick with the dependency resolver adapter; an adapter for the activator is easily created for anyone who needs it, as you can see.

For ASP.NET Core however, we went into a different direction, and as you can see in the documentation, the integration package actually contains a SimpleInjectorControllerActivator out of the box. In ASP.NET Core, the controller activator is the perfect interception point and due to the OWIN-like pipeline, a scope can be easily wrapped around a request. So with ASP.NET Core, the advised practice is to use the controller activator as interception point.

Using Simple Injector in Web API and OWIN

I had the same issue but with UnityDependencyResolver. But I think it should also work for SimpleInjectorWebApiDependencyResolver. Try to register your resolver like this (as a Property of HttpConfiguration):

public void Configuration(IAppBuilder app)
{
var container = GetContainer(); // Initialise container

HttpConfiguration config = new HttpConfiguration
{
DependencyResolver = new SimpleInjectorWebApiDependencyResolver(container);
};

WebApiConfig.Register(config);
app.UseWebApi(config);
}

Simple Injector with multiple WebAPI projects

RegisterWebApiControllers uses reflection under the covers to search for implementations of ApiController.

I guess, based upon the error you get, project B is referenced by project A and the call to container.RegisterWebApiControllers in project A finds and registers the controllers of project B also.

Now when .Verify() is called it will scan the constructors of the ApiControllers in project B, finds a dependency on IUserService and breaks because this registration is actually missing in project A.

The integration package contains another overload for RegisterWebApiControllers which takes an array of assemblies that must be scanned for ApiControllers instead of scanning through all referenced assemblies.

Assuming the assembly of project A contains all ApiControllers that need to be registered this overload can be used in project A like:

container.RegisterWebApiControllers(GlobalConfiguration.Configuration,
new[] {typeof(MyApiControllerInProjectA).Assembly});


Related Topics



Leave a reply



Submit