Please help me out of a rabbit hole with NInject and Web API 2. I have a WebApi project. I installed the Ninject.Web.WebApi.WebHost v3.3.0 Nuget. This brings in
One of these has generated a Ninject.Web.Common.cs in the App_Start folder. I modified the RegisterServices method in it for my graph:
/// <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>();
}
The module being loaded contains a binding for IQuerySubscription:
namespace SubscriptionApi.Models
{
...
public class SubscriptionApiModule : NinjectModule
{
public override void Load()
{
Bind<IQuerySubscription>().To<QueryMultipubForSubscription>();
...
}
}
}
I am pretty confident in the configuration for SubscriptionApiModule. I have unit tests that provide evidence that a StandardKernel with a SubscriptionApiModule will respond to .Get requests with concrete classes I expect.
I have a few controllers. Here is one:
[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);
}
}
I added a Heartbeat for diagnosis. I run the API and in a browser address I enter http://localhost:xxxxx/api/SubscriptionCheck/Heartbeat and am presented with the response:
<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>
The container has not, apparently, been registered with the Web Api 2 framework. I applied an old hack that used to work, sometimes. In the CreateKernel method, after RegisterServices(kernel):
GlobalConfiguration.Configuration.DependencyResolver = new NinjectDependencyResolver(kernel);
This gets me an exception at startup:
Ninject.ActivationException HResult=0x80131500 Message=Error activating ModelValidatorProvider using binding from ModelValidatorProvider to NinjectDefaultModelValidatorProvider A cyclical dependency was detected between the constructors of two services.
Activation path: 3) Injection of dependency ModelValidatorProvider into parameter defaultModelValidatorProviders of constructor of type DefaultModelValidatorProviders 2) Injection of dependency DefaultModelValidatorProviders into parameter defaultModelValidatorProviders of constructor of type NinjectDefaultModelValidatorProvider 1) Request for ModelValidatorProvider
Suggestions: 1) Ensure that you have not declared a dependency for ModelValidatorProvider on any implementations of the service. 2) Consider combining the services into a single one to remove the cycle. 3) Use property injection instead of constructor injection, and implement IInitializable if you need initialization logic to be run after property values have been injected.
Source= StackTrace:
I tried a hack I read somewhere in SO for this. I added into the CreateKernel, under the call to RegisterServices and before the assignment to the .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);
This gives me the exception:
Ninject.ActivationException HResult=0x80131500 Message=Error activating DefaultModelValidatorProviders More than one matching bindings are available. Matching bindings: 1) binding from DefaultModelValidatorProviders to constant value 2) binding from DefaultModelValidatorProviders to constant value Activation path: 2) Injection of dependency DefaultModelValidatorProviders into parameter defaultModelValidatorProviders of constructor of type NinjectDefaultModelValidatorProvider 1) Request for ModelValidatorProvider
Suggestions: 1) Ensure that you have defined a binding for DefaultModelValidatorProviders only once.
Source= StackTrace:
Can you offer a way I can get NInject to be registered with WebApi controllers?
User contributions licensed under CC BY-SA 3.0