Пожалуйста, помогите мне выйти из кроличьей норы с помощью 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?