Инъекция зависимостей для ASP.NET WebAPI ActionFilters с использованием Ninject не работает

Я пытаюсь настроить DI на ActionFilters в ASP.NET WebAPI, используя Ninject. Я выполнил следующие инструкции: https://github.com/ninject/Ninject.Web.WebApi/wiki/Dependency-injection-for-filters

Я создаю свой ActionFilter следующим образом:

public class ApiAuthorizeFilter : AbstractActionFilter
{
    private readonly IValidateApiTokenService _validateApiTokenService;

    public ApiAuthorizeFilter(IValidateApiTokenService validateApiTokenService)
    {
        _validateApiTokenService = validateApiTokenService;
    }

    public override bool AllowMultiple => true;

    public override void OnActionExecuting(HttpActionContext actionContext)
    {
    }

    public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
    {
    }
}

Я сконфигурирован так:

kernel.BindHttpFilter<ApiAuthorizeFilter>(FilterScope.Controller);

Мое понимание, основанное на информации по вышеуказанной ссылке, заключается в том, что ActionFilter должен запускаться для всех действий во всех контроллерах WebAPI. Тем не менее, я установил точки останова как при переопределенных методах в фильтре, так и в них никогда не попадает. Я установил точку останова в конфигурации и могу подтвердить, что она выполняется.

Что мне не хватает? Мне нужен этот ActionFilter для запуска всех действий в каждом ApiController в моем проекте.

Ответ 1

в вашем классе запуска

public void Configuration(IAppBuilder app)
{    
    var kernel = new StandardKernel();
    // register IValidateApiTokenService
    var config = new HttpConfiguration();
    config.Filters.Add(new ApiAuthorizeFilter(kernel.Get<IValidateApiTokenService>());
}

Ответ 2

Причина, по которой это не работает, заключается в том, что ActionFilters (или любые фильтры, если на то пошло) создаются в виде одиночек по времени выполнения (один раз навсегда в контексте приложения), и вообще любой контейнер DI имеет проблемы с подключением объектные переходные и/или одноразовые зависимости, если этот объект является одиночным.

Одним из решений вашей проблемы будет использование встроенного локатора сервисов, например: DependencyResolver.Current.GetService(typeof(IValidateApiTokenService));

Я лично не использую Ninject для своих потребностей DI, но если выше это не работает, возможно, потребуется некоторое подключение к началу DI или использовать интеграционный пакет, подобный этому: https://github.com/ninject/ninject.web.mvc/wiki/MVC3

Ответ 3

Я никогда не работал над Ninject, я работал над Unity. Имея опыт работы с Unity, я попытаюсь пролить свет на проблему.

Я не уверен, в чем цель _validateApiTokenService, но то, что я могу наблюдать из вышеприведенного кода, заключается в том, что вам нужно настроить привязку зависимости к реализации IValidateApiTokenService. Наряду со следующим кодом

kernel.BindHttpFilter<ApiAuthorizeFilter>(FilterScope.Controller);

возможно, вам нужно что-то вроде

kernel.Bind<IValidateApiTokenService>().To<ValidateApiTokenService>();

или

kernel.Bind<IValidateApiTokenService>.To<ValidateApiTokenService>().InSingletonScope(); 

если он находится в области Singleton.