I've got a simple web application using ASP.NET MVC3 and Ninject.Web.MVC (the MVC3 version).
The whole thing is working fine, except when the application ends. Whenever it ends, the kernel is disposed, as seen in Application_End() in NinjectHttpApplication:
Reflector tells me this:
public void Application_End()
{
lock (this)
{
if (kernel != null)
{
kernel.Dispose();
kernel = null;
}
this.OnApplicationStopped();
}
}
What happens is that my webserver goes down with a StackOverflowException (I tried both IIS7 and the built-in webserver in VS2010). I can only assume this is where it's going wrong, as I haven't written any code myself on application end.
I figured out that the Kernel knows how to resolve IKernel (which returns the Kernel itself), might this be something that could cause the stack overflow? I could imagine something like this happens:
In other words, the kernel gets disposed, disposes all references it holds (which includes a self-reference), which causes it to dispose itself.
Does this make any sense?
It seems the problem is in NinjectHttpApplication. Take a look at this activation code:
public void Application_Start()
{
lock (this)
{
kernel = this.CreateKernel();
...
kernel.Bind<IResolutionRoot>().ToConstant(kernel).InSingletonScope();
...
}
}
It seems ok, but what's happening now is that whenever an IResolutionRoot is called, kernel is cached within itself. When disposing the kernel, the cache is emptied which disposes all cached objects, which causes a circular reference.
A simple solution for NinjectHttpApplication would be to simply change the binding. Change the constant binding to a method one:
kernel.Bind<IResolutionRoot>().ToConstant(kernel).InSingletonScope();
becomes
kernel.Bind<IResolutionRoot>().ToMethod(x => this.Kernel);
This solves the problem, but I am not sure if the whole circular dispose caching issue is a bug in ninject.
I encountered the same issue.
I ended up copying the code for NinjectHttpApplication
and removing Kernel.Dispose()
in the Application_End
function.
public void Application_End()
{
lock (this)
{
if (kernel != null)
{
//kernel.Dispose();
kernel = null;
}
this.OnApplicationStopped();
}
}
That should fix the error. Not sure if there is a planned fix for it though.
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