2

I have an issue with my datacontext getting disposed every once in a while in one of my filters attached to my web api controllers. Is this the correct way to setup a filter for my Web API controllers and why does my datacontext get disposed sometimes?

The operation cannot be completed because the DbContext has been disposed.

Global.asax

GlobalConfiguration.Configuration.Filters
               .Add(new ApiValidationFilter(kernel.Get<IApiAuthenticationService>()));

kernel.Bind<IDatabaseFactory>()
      .To<DatabaseFactory>()
      .InScope(q => HttpContext.Current ?? StandardScopeCallbacks.Thread(q));

ApiValidationFilter.cs

public class ApiValidationFilter : System.Web.Http.Filters.IActionFilter
    {
            private readonly IApiAuthenticationService _apiAuthenticationService;

            public ApiValidationFilter(
                IApiAuthenticationService apiAuthenticationService)
            {
                _apiAuthenticationService = apiAuthenticationService;
            }
cuongle
  • 74,024
  • 28
  • 151
  • 206
Mike Flynn
  • 22,342
  • 54
  • 182
  • 341

2 Answers2

1

You should be using the Filter binding syntax, then Ninject will handle the the filter lifetime, and it will also handle the constructor injection of the filter.

https://github.com/ninject/ninject.web.mvc/wiki/Filter-configurations

I would also let Ninject handle managing the lifetime of the data conext as well, instead of using a factory.

kernel.Bind<MyContext>().ToSelf().InRequestScope();  

Alternatively, if you want better testability you can derive your context from an interface and bind to that. The InRequestScope makes sure the context lives for the entire web request, and it will automatically get disposed when the request is done. You don't have to remember to do so, and there won't be any memory leaks by holding onto a request longer than a single request.

You can see an example here:

ASP.NET MVC 3 and Global Filter Injection

Community
  • 1
  • 1
Erik Funkenbusch
  • 92,674
  • 28
  • 195
  • 291
  • I did try the BindFilter but it doesnt work with Web API, only regular controllers. With respect to InRequestScope, I need the threading because I have some services running on different threads on some actions. – Mike Flynn Sep 30 '12 at 03:45
  • @MikeFlynn - Didn't notice this was a WebApi. Regardless, use the Ninject.Web.WebApi extension which uses .BindHttpFilter instead. Regarding your comment about threads.. You do know that Data Contexts are not thread safe, right? Don't use them across multiple threads. Regardless it shouldn't matter, .InRequestScope won't destroy the context until the request has finished, and if you've got threads running after a request has ended, you've got far more problems with your architecture than we can solve. – Erik Funkenbusch Sep 30 '12 at 06:32
  • Ninject.Web.WebApi I believe was for Beta and is depreciated. – Mike Flynn Sep 30 '12 at 07:23
  • @MikeFlynn - Well, you'll have to take that up with Remo then, since the nugget package clearly says it's for RTM http://nuget.org/packages/Ninject.Web.WebApi-RC – Erik Funkenbusch Sep 30 '12 at 08:20
  • Sorry it was Ninject.WebApi that is depreciated...I assume there not the same thing. – Mike Flynn Sep 30 '12 at 17:13
  • @MikeFlynn - FYI, it's Deprecated, not Depreciated. They are very different things. But my point still stands, use the Filter binding syntax. – Erik Funkenbusch Sep 30 '12 at 18:14
0

I eventually had to resort to the following, nothing worked.

var apiRepository = new ApiRepository(new DatabaseFactory());
                var apiAuthenticationService = new ApiAuthenticationService(apiRepository, new UnitOfWork(new DatabaseFactory()), new ValidationProvider(null));
Mike Flynn
  • 22,342
  • 54
  • 182
  • 341