WebApi Ninject with InRequestScope with OPTIONS call

830 views Asked by At

I a have set up my webApi application so that the Entity Framework DBContent is injected using RequestScope.Each repository takes a DbContext as a constructor argument, which is injected using Ninject.

However I appear to have a problem with pre flighted requests (OPTIONS calls).

When the OPTIONS call is received the appropriate repositories are created and use one DbContext per request, which is diposed as expected when the request returns (200).

The associated GET calls are then made.

What I am seeing is that no new DbContext is being created for these calls. The repository attempts to access the Context that was disposed at the end of the OPTIONS call.

Is this expected?? Am I missing something in my configuration?

Here is some trace output

You can see that the first attempt to use the DB after the GET request fails as the DbContext with ID 39bb041e-6098-4606-a4c0-aa5db2e8c6ed was disposed in previous OPTIONS call.

Process request: OPTIONS : http://localhost:52351/api/v1/aroute
Process request: OPTIONS : http://localhost:52351/api/v1/broute
Creating ctx 190d88ba-2781-4ba8-9b90-07d6af937fe9 at 18/06/2015 9:03:51 p.m.
Create ARepository
Creating ctx 39bb041e-6098-4606-a4c0-aa5db2e8c6ed at 18/06/2015 9:03:51 p.m.
Create BRepository
Create CRepository
Process response: OK
Process response: OK
Disposing of 190d88ba-2781-4ba8-9b90-07d6af937fe9 at 18/06/2015 9:03:51 p.m.
Disposing of 39bb041e-6098-4606-a4c0-aa5db2e8c6ed at 18/06/2015 9:03:51 p.m.
Process request: GET : http://localhost:52351/api/v1/aroute
Process request: GET : http://localhost:52351/api/v1/broute
'iisexpress.exe' (CLR v4.0.30319: /LM/W3SVC/1839635423/ROOT-1-130790918249781429): Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Numerics\v4.0_4.0.0.0__b77a5c561934e089\System.Numerics.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
AccessDbMethod using 39bb041e-6098-4606-a4c0-aa5db2e8c6ed
A first chance exception of type 'System.InvalidOperationException' occurred in EntityFramework.dll

A Repository:

    public ARepository(DbContext context)
    {
        _context = context;
    }

NinjectWebCommon:

    public static void Start() 
    {
        DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
        //tried with and without following line
        DynamicModuleUtility.RegisterModule(typeof(Ninject.Web.Common.NinjectHttpModule)); 
        DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
        bootstrapper.Initialize(CreateKernel);
    }

    private static void RegisterServices(IKernel kernel)
    {
        //Ensure we only have ONE per request
        kernel.Bind<DbContext>().ToSelf().InRequestScope();
    }

I have the following packages installed:

  <package id="Microsoft.AspNet.Cors" version="5.2.2" targetFramework="net451" />
  <package id="Microsoft.AspNet.Mvc" version="5.2.2" targetFramework="net451" />
  <package id="Microsoft.AspNet.Razor" version="3.2.2" targetFramework="net451" />
  <package id="Microsoft.AspNet.Web.Optimization" version="1.1.3" targetFramework="net451" />
  <package id="Microsoft.AspNet.WebApi" version="5.2.2" targetFramework="net451" />
  <package id="Microsoft.AspNet.WebApi.Client" version="5.2.3" targetFramework="net451" />
  <package id="Microsoft.AspNet.WebApi.Core" version="5.2.3" targetFramework="net451" />
  <package id="Microsoft.AspNet.WebApi.Cors" version="5.2.2" targetFramework="net451" />
  <package id="Microsoft.AspNet.WebApi.HelpPage" version="5.2.2" targetFramework="net451" />
  <package id="Microsoft.AspNet.WebApi.WebHost" version="5.2.2" targetFramework="net451" />
  <package id="Ninject" version="3.2.2.0" targetFramework="net451" />
  <package id="Ninject.Web.Common" version="3.2.3.0" targetFramework="net451" />
  <package id="Ninject.Web.Common.WebHost" version="3.2.3.0" targetFramework="net451" />
  <package id="Ninject.Web.WebApi" version="3.2.4.0" targetFramework="net451" />
  <package id="Ninject.Web.WebApi.WebHost" version="3.2.4.0" targetFramework="net451" />
2

There are 2 answers

0
Kildareflare On BEST ANSWER

The solution is pretty simple and I guessed at it while pondering the problem just before I went to sleep. I had earlier changed the lifetime of the repositories to singleton to test another problem.

Thus, whilst the context had a scope of per request, the repositories which consumed it did not. Due to having singleton scope, they were never disposed off and thus on the next request, attempted to access a context which no longer existed.

Moral: try not to multi-task, especially not late at night after a full day of work.

0
unnilhexium On

I had the same problem a while back.

try using it this way.

kernel.Bind<DbContext>().ToSelf().InScope(c => c.Request);