NInject v3.3.4 и WebApi 2, конструктор без параметров - PullRequest
0 голосов
/ 16 апреля 2019

Пожалуйста, помогите мне выйти из кроличьей норы с помощью NInject и Web API 2. У меня есть проект WebApi. Я установил Ninject.Web.WebApi.WebHost v3.3.0 Nuget. Это приносит

  • Ninject.Web.WebApi.WebHost v3.3.0
  • Ninject.Web.WebApi v3.3.0
  • Ninject.Web.Common.WebHost v3.3.1
  • Ninject.Web.Common v3.3.1
  • Ninject v3.3.4

Один из них сгенерировал Ninject.Web.Common.cs в папке App_Start. Я изменил метод RegisterServices в нем для моего графика:

    /// <summary>
    /// Load your modules or register your services here!
    /// </summary>
    /// <param name="kernel">The kernel.</param>
    private static void RegisterServices(IKernel kernel)
    {
        kernel.Load<SubscriptionApiModule>();
    }

Загружаемый модуль содержит привязку для IQuerySubscription:

    namespace SubscriptionApi.Models
    {
    ...
        public class SubscriptionApiModule : NinjectModule
        {
            public override void Load()
            {
                Bind<IQuerySubscription>().To<QueryMultipubForSubscription>();
                ...
            }
        }
    }

Я довольно уверен в конфигурации для SubscriptionApiModule. У меня есть модульные тесты, которые подтверждают, что StandardKernel с SubscriptionApiModule будет отвечать. Получать запросы с конкретными классами, которые я ожидаю.

У меня есть несколько контроллеров. Вот один из них:

[RoutePrefix("api/SubscriptionCheck")]
public class SubscriptionCheckController : ApiController
{
    public SubscriptionCheckController(IQuerySubscription queryService)
    {
        QueryService = queryService;
    }

    private IQuerySubscription QueryService { get; }

    [HttpGet]
    [Route("Heartbeat")]
    public string Heartbeat()
    {
        return "thump";
    }

    [HttpGet] 
    [Route("Get/{email}/{productCode}")]
    [EnableCors(origins: "*", headers: "*", methods:"*")]
    public async Task<bool> Get(string email, string productCode)
    {
        return await QueryService.IsSubscribed(email, productCode);
    }
}

Я добавил сердцебиение для диагностики. Я запускаю API и в адрес браузера ввожу http://localhost:xxxxx/api/SubscriptionCheck/Heartbeat и получаю ответ:

<Error>
    <Message>An error has occurred.</Message>
    <ExceptionMessage>
        An error occurred when trying to create a controller of type 'SubscriptionCheckController'. Make sure that the controller has a parameterless public constructor.
    </ExceptionMessage>
    <ExceptionType>System.InvalidOperationException</ExceptionType>
    <StackTrace>
        at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType) at System.Web.Http.Controllers.HttpControllerDescriptor.CreateController(HttpRequestMessage request) at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__15.MoveNext()
        </StackTrace>
        <InnerException>
            <Message>An error has occurred.</Message>
            <ExceptionMessage>
                Type 'SubscriptionApi.Controllers.SubscriptionCheckController' does not have a default constructor
            </ExceptionMessage>
            <ExceptionType>System.ArgumentException</ExceptionType>
            <StackTrace>
                at System.Linq.Expressions.Expression.New(Type type) at System.Web.Http.Internal.TypeActivator.Create[TBase](Type instanceType) at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.GetInstanceOrActivator(HttpRequestMessage request, Type controllerType, Func`1& activator) at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)
            </StackTrace>
        </InnerException>
</Error>

Контейнер, по-видимому, не был зарегистрирован в фреймворке Web Api 2. Я применил старый хак, который раньше работал, иногда. В методе CreateKernel после RegisterServices (ядро):

GlobalConfiguration.Configuration.DependencyResolver = new NinjectDependencyResolver(kernel);

При запуске появляется исключение:

Ninject.ActivationException HResult = 0x80131500 Сообщение = Ошибка активации ModelValidatorProvider с использованием привязки от ModelValidatorProvider к NinjectDefaultModelValidatorProvider Была обнаружена циклическая зависимость между конструкторами двух сервисов.

Путь активации: 3) Инъекция зависимости ModelValidatorProvider в параметр defaultModelValidatorProviders конструктора типа DefaultModelValidatorProviders 2) Внедрение зависимости DefaultModelValidatorProviders в параметр defaultModelValidatorProviders конструктора типа NinjectDefaultModelValidatorProvider 1) Запрос на модель ValidatorProvider

Предложения: 1) Убедитесь, что вы не объявили зависимость для ModelValidatorProvider ни в одной реализации сервиса. 2) Рассмотрите возможность объединения сервисов в один, чтобы удалить цикл. 3) Использовать внедрение свойств вместо внедрения конструктора и реализовать IInitializable если вам нужно запустить логику инициализации после введения значений свойств.

Источник = Трассировки стека:

Я попытался взломать, я читал где-то в SO для этого. Я добавил в CreateKernel, при вызове RegisterServices и перед назначением .DependencyResolver:

            System.Collections.Generic.IEnumerable<object> configuredObjects =
                GlobalConfiguration.Configuration.Services.GetServices(
                    typeof(System.Web.Http.Validation.ModelValidatorProvider));
            System.Collections.Generic.IEnumerable<System.Web.Http.Validation.ModelValidatorProvider> configuredProviders =
                configuredObjects.Cast<System.Web.Http.Validation.ModelValidatorProvider>();
            Ninject.Web.WebApi.Filter.DefaultModelValidatorProviders defaultProviders =
                new Ninject.Web.WebApi.Filter.DefaultModelValidatorProviders(configuredProviders);
            kernel
                .Bind<Ninject.Web.WebApi.Filter.DefaultModelValidatorProviders>()
                .ToConstant(defaultProviders);

Это дает мне исключение:

Ninject.ActivationException HResult = 0x80131500 Сообщение = Ошибка активации DefaultModelValidatorProviders Доступно несколько подходящих привязок. Соответствующие привязки: 1) привязка из DefaultModelValidatorProviders к постоянному значению 2) привязка из DefaultModelValidatorProviders к постоянному значению Путь активации: 2) Внедрение зависимости DefaultModelValidatorProviders в параметр defaultModelValidatorProviders конструктора типа NinjectDefaultModelValidatorProvider 1) Запрос на модель ValidatorProvider

Предложения: 1) Убедитесь, что вы определили привязку для DefaultModelValidatorProviders только один раз.

Источник = Трассировки стека:

Можете ли вы предложить способ регистрации NInject на контроллерах WebApi?

...