I am currently using Simple Injector to resolve dependencies into my Asp.Net Web Api projects.
From the documentation you can configure it like that:
protected void Application_Start() {
// Create the container as usual.
var container = new Container();
container.Options.DefaultScopedLifestyle = new WebApiRequestLifestyle();
// Register your types, for instance using the scoped lifestyle:
container.Register<IUserRepository, SqlUserRepository>(Lifestyle.Scoped);
// This is an extension method from the integration package.
container.RegisterWebApiControllers(GlobalConfiguration.Configuration);
container.Verify();
GlobalConfiguration.Configuration.DependencyResolver =
new SimpleInjectorWebApiDependencyResolver(container);
// Here your usual Web API configuration stuff.
}
The main points here are to register the Web Api controllers and set a custom dependency resolver.
However I've just read these article from Mark Seemann on how to configure dependency injection in Asp.Net Web Api:
From these articles, I've learnt that there is a better option than implementing IDependencyResolver
to resolve Web Api dependencies.
This other option is to create an implementation of the IHttpControllerActivator
that acts as an Adapter over the IoC Container.
Here is the implementation I've coded using SimpleInjector:
public class SimpleInjectorControllerActivator : IHttpControllerActivator
{
private readonly Container _container;
public SimpleInjectorControllerActivator(Container container)
{
_container = container;
}
public IHttpController Create(HttpRequestMessage request,
HttpControllerDescriptor controllerDescriptor, Type controllerType)
{
request.RegisterForDispose(_container.BeginExecutionContextScope());
return (IHttpController)_container.GetInstance(controllerType);
}
}
and in the Application_Start
method, I've replaced this line:
GlobalConfiguration.Configuration.DependencyResolver =
new SimpleInjectorWebApiDependencyResolver(container);
by this line :
GlobalConfiguration.Configuration.Services.Replace(
typeof(IHttpControllerActivator),
new SimpleInjectorControllerActivator(container));
I would like to know if the implementation of the IHttpControllerActivator
is valid and also if this approach is valid and will work as good as the normal one ?
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.
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