Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ninject.Web.MVC + MVC3 throws StackOverflowException

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:

  • Kernel.Dispose()
  • Dispose all instances in the kernel
  • hey! look at this, the kernel is also in the kernel. Return to step 1.

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?

Edit:

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.

like image 890
Erik van Brakel Avatar asked Dec 01 '10 17:12

Erik van Brakel


Video Answer


1 Answers

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.

like image 165
Omar Avatar answered Oct 11 '22 17:10

Omar