Reputation: 1643
I have an ASP.MVC project where I am using ninject for the IOC container. I have added the binding as a separate class within an Infrastructure folder like this:
public class NinjectControllerFactory : DefaultControllerFactory{
private readonly IKernel _ninjectKernal;
public NinjectControllerFactory()
{
_ninjectKernal = new StandardKernel();
PSCCheckContext m = _ninjectKernal.Get<PSCCheckContext>(new IParameter[]
{ new ConstructorArgument("appNamekey", "Name of Staff Application"),
new ConstructorArgument("serverLocationNameKey", "Location of Application Server") });
AddBindings();
}
So you can see that I am trying to set two parameters from the web.config in the constructor of the PSCCheckContext. This is another C# application that handles access to the db. The AddBindings() class just maps the interface classes to the concrete implementations as you would expect:
private void AddBindings()
{
...
_ninjectKernal.Bind<IPSCCheckContext>().To<PSCCheckContext>();
}
The problem I am having is that there are 2 constructors in the PSCCheckContext class where the second one takes a different parameter:
public class PSCCheckContext : IPSCCheckContext
{
public PSCCheckContext(string appNamekey, string serverLocationNameKey);
public PSCCheckContext(string imgNamekey, string imgFlagKey, string serverLocationKeyName);
When I try and hit the controller that Ninject injects this binding I get an error that:
Error activating string. No matching bindings are available, and the type is not self-bindable.
Activation path:
3) Injection of dependency string into parameter imgNamekey of constructor of type PSCCheckContext
2) Injection of dependency IPSCCheckContext into parameter pscCheckContext of constructor of type AccountController
1) Request for AccountController
Suggestions:
1) Ensure that you have defined a binding for string.
2) If the binding was defined in a module, ensure that the module has been loaded into the kernel.
3) Ensure you have not accidentally created more than one kernel.
4) If you are using constructor arguments, ensure that the parameter name matches the constructors parameter name.
5) If you are using automatic module loading, ensure the search path and filters are correct.
Even if I change the binding to be better (having read http://thebrainyprofessionals.com/2013/05/20/passing-constructor-parameters-in-ninject/)
IParameter appNamekey = new ConstructorArgument("appNamekey", "Name of Staff Application");
IParameter serverLocationNameKey = new ConstructorArgument("serverLocationNameKey", "Location of Application Server");
_ninjectKernal.Bind<IPSCCheckContext>().To<PSCCheckContext>()
.WithConstructorArgument(appNamekey)
.WithConstructorArgument(serverLocationNameKey);
I still get the same error. I have read various SO questions:
Inject value into injected dependency
Creating an instance using Ninject with additional parameters in the constructor
Convention based binding of constructor string arguments with Ninject
but none seem to be having my problem.
What am I doing wrong?
I can't remove the additional constructor as it is in a different application and I think it is being used by a different system.
Here's the AccountController constructor for completeness
public class AccountController : BaseController
private readonly IPSCCheckContext _pscCheckContext;
public AccountController(IPSCCheckContext pscCheckContext)
{
this._pscCheckContext = pscCheckContext;
Upvotes: 2
Views: 10235
Reputation: 15579
You can also try this:
kernel.Bind<IPSCCheckContext>().ToConstructor(ctorArg => new PSCCheckContext(
"Name of Staff Application",
"Location of Application Server"));
I prefer this over WithConstructorArgument
, since if you ever change the arg name, your DI binding will not break.
Upvotes: 6
Reputation: 13243
The code in your question is broken. See:
public NinjectControllerFactory()
{
_ninjectKernal = new StandardKernel();
PSCCheckContext m = _ninjectKernal.Get<PSCCheckContext>(new IParameter[]
{ new ConstructorArgument("appNamekey", "Name of Staff Application"),
new ConstructorArgument("serverLocationNameKey", "Location of Application Server") });
AddBindings();
}
Specifically:
PSCCheckContext m = _ninjectKernal.Get<PSCCheckContext>(new IParameter[]
{ new ConstructorArgument("appNamekey", "Name of Staff Application"),
new ConstructorArgument("serverLocationNameKey", "Location of Application Server") });
What's this supposed to be doing? What it actually does is have ninject instanciate one PSCheckContext
instance and then it forget's about it. Unless the ctor of PSCCheckContext
has side effects on the system (which would not be a good programming practice), this code does not have any effect whatsoever (apart from consuming CPU time and memory) (=> notice that PSCCheckContext m
is a local variable, so it can't be reused later).
I guess what you meant to do was:
public NinjectControllerFactory()
{
_ninjectKernal = new StandardKernel();
_ninjectKernal.Bind<IPSCCheckContext>().To<PSCCheckContext>()
.WithConstructorArgument("appNamekey", "Name of Staff Application")
.WithConstructorArgument("serverLocationNameKey", "Location of Application Server");
AddBindings();
}
This binds IPSCCheckContext
with constructor arguments so that from now on it should be injectable into the controller.
Upvotes: 3