Ninject WebAPI Операция не может быть завершена, поскольку DbContext был удален

Итак, я использую простой шаблон репозитория с атрибутами и фильтрами, как рекомендовал здесь, так как я использую пакет Ninject.Web.WebApi-RC из NuGet.

Это работает для первого запроса, но поскольку у меня есть область DbContext в запросе, она размещается во всех последующих запросах.

Вот мой атрибут:

public class CommunicationKeyValidationAttribute : FilterAttribute
{
}

Вот мой фильтр:

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

Вот мой репозиторий:

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

Вот мои привязки Ninject:

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

Мой контроллер выглядит следующим образом:

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

Проблема здесь в том, что конструктор на CommunicationKeyValidationFilter вызывается только при первом запросе. Есть ли способ, которым я могу заставить ninject создавать этот фильтр каждый раз, когда он пытается разрешить фильтр?

Ответ 1

Фильтры кэшируются WebApi. Они должны быть в переходном режиме, чтобы WebApi мог управлять жизненным циклом. Из-за длительного жизненного цикла у вас не может быть никакой зависимости, которая имеет более короткий жизненный цикл.

Однако вы можете создать свой репозиторий во время выполнения фильтра. Для этого лучше всего ввести factory с помощью 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();