Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ninject WebAPI The operation cannot be completed because the DbContext has been disposed

So I am using a simple repository pattern with Attributes and Filters as recommended here since I am using the Ninject.Web.WebApi-RC package from NuGet.

This works for the first request but since I have my DbContext in request scope, it is disposed on all subsequent requests.

Here is my attribute:

public class CommunicationKeyValidationAttribute : FilterAttribute
{
}

Here is my filter:

public class CommunicationKeyValidationFilter : AbstractActionFilter
{
    public CommunicationKeyValidationFilter(IRepository repository)
    {
        this.repository = repository;
    }
    public override void OnActionExecuting(HttpActionContext actionContext)
    {
        // do stuff
    }
 }

Here is my repository:

public class Repository : IRepository
{
    public Repository(MyDbContext dbContext)
    {
        this.dbContext = dbContext;
    }
}

Here are my Ninject bindings:

this.Kernel.Bind<MyDbContext>().ToSelf().InRequestScope();
this.Kernel.Bind<IRepository>().To<Repository>().InRequestScope();
this.Kernel.BindHttpFilter<CommunicationKeyValidationFilter>(FilterScope.Action)
        .WhenActionMethodHas<CommunicationKeyValidationAttribute>()
        .InRequestScope();

My controller looks like this:

public class HomeController 
{
    [CommunicationKeyValidation]
    public ActionResult Index()
    {
        // do stuff
    }

The issue here is that the constructor on CommunicationKeyValidationFilter is only being called on the first request. Is there a way that I can cause ninject to construct this filter each time it attempts to resolve the filter?

like image 236
John Kalberer Avatar asked Mar 11 '13 21:03

John Kalberer


1 Answers

Filters are cached by the WebApi. They should be in transient scope so that it the WebApi can manage the lifecycle. Because of the long lifecycle you can't have any dependency that have a shorter lifecycle.

What you can do though is to create your repository during execution of the filter. For this it is best to inject a factory using the NinjectFactoryExtension:

public class CommunicationKeyValidationFilter : AbstractActionFilter
{
    public CommunicationKeyValidationFilter(IRepositoryFactory repositoryFactory)
    {
        this.repositoryFactory = repositoryFactory;
    }

    public override void OnActionExecuting(HttpActionContext actionContext)
    {
        var repository = this.repositoryFactory.CreateRepository();
    }
 }

 public interface IRepositoryFactory { IRepository CreateRepository(); }
 kernel.Bind<IRepositoryFactory>().ToFactory();
like image 57
Remo Gloor Avatar answered Oct 24 '22 11:10

Remo Gloor