I have a custom IHttpControllerActivator
for my web api controllers which I'm using along with simple injector:
public sealed class ApiControllerActivator : IHttpControllerActivator
{
private readonly Container _container;
private readonly IHttpControllerActivator _original;
public ApiControllerActivator(Container container, IHttpControllerActivator original)
{
_container = container;
_original = original;
}
public IHttpController Create(HttpRequestMessage request,
HttpControllerDescriptor controllerDescriptor, Type controllerType)
{
var controller = CreateController(request, controllerDescriptor, controllerType);
// request.RegisterForDispose(...); required?
return controller;
}
private IHttpController CreateController(HttpRequestMessage request,
HttpControllerDescriptor controllerDescriptor, Type controllerType)
{
if (controllerType.IsSubclassOf(typeof(WebApiController)))
{
return (IHttpController) _container.GetInstance(controllerType);
}
return _original.Create(request, controllerDescriptor, controllerType);
}
}
Registration:
GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpControllerActivator), new ApiControllerActivator(container, GlobalConfiguration.Configuration.Services.GetHttpControllerActivator()));
Do I need to handle any disposal of the controller, or is it handled by the framework?
Do I need to handle any disposal of the controller
The short answer is: as long as you register your Web API controllers using the RegisterWebApiControllers()
extension method, you do not need to handle the disposal of your controllers.
The long answer is that when you call RegisterWebApiControllers
, Simple Injector will actually not dispose your controllers at all, but you will get a VerificationException
when you override Dispose(bool)
in one of your controllers when you call Container.Verify()
.
The reasoning is as follows: Simple Injector will only dispose of disposable classes when they are registered as either Scoped
or Singleton
. Transient
registrations are never disposed. The RegisterWebApiControllers
extension method, however, registers controllers as Transient
.
When registering a disposable Transient
in Simple Injector, it would typically cause a DisposableTransientComponent
warning, when Verify
is called. Since, however, the ApiController
base class does implement IDisposable
, but its Dispose(bool)
method is a no-op, not disposing it is not be a problem, unless the derived controller explicitly overrides Dispose(bool)
.
Because of that, RegisterWebApiControllers
simply suppresses this warning when it makes the registration. When it finds that the derived controller class does override Dispose(bool)
, however, it will discard the suppression and you will see Verify()
warn you about this disposable type, because not disposing such type would be a problem.
The idea behind this behavior is that the need to actually implement disposable logic on a controller would be really rare, because a controller itself would typically not have to deal with unmanaged resources. This is typically something that lower level components will do, but, when registered correctly, those components will be disposed by Simple Injector. If you have a controller that has dispose logic, you should consider refactoring it and moving that resource out of the controller, into a different component.
In the extremely rare case that having dispose logic on a controller itself makes the most sense, you will either have to:
Scoped
Scope
using container.RegisterInitializer<MyControllerType>(c => Lifestyle.Scope.RegisterForDisposal(container, c));