Ninject WithConstructorArgument : No matching bindings are available, and the type is not self-bindable
Asked Answered
D

2

24

My understanding of WithConstructorArgument is probably erroneous, because the following is not working:

I have a service, lets call it MyService, whose constructor is taking multiple objects, and a string parameter called testEmail. For this string parameter, I added the following Ninject binding:

string testEmail = "[email protected]";
kernel.Bind<IMyService>().To<MyService>().WithConstructorArgument("testEmail", testEmail);

However, when executing the following line of code, I get an exception:

var myService = kernel.Get<MyService>();

Here is the exception I get:

Error activating string No matching bindings are available, and the type is not self-bindable. Activation path:
2) Injection of dependency string into parameter testEmail of constructor of type MyService
1) Request for MyService

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.

What am I doing wrong here?

UPDATE:

Here is the MyService constructor:

[Ninject.Inject]
public MyService(IMyRepository myRepository, IMyEventService myEventService, 
                 IUnitOfWork unitOfWork, ILoggingService log,
         IEmailService emailService, IConfigurationManager config,
         HttpContextBase httpContext, string testEmail)
{
    this.myRepository = myRepository;
    this.myEventService = myEventService;
    this.unitOfWork = unitOfWork;
    this.log = log;
    this.emailService = emailService;
    this.config = config;
    this.httpContext = httpContext;
    this.testEmail = testEmail;
}

I have standard bindings for all the constructor parameter types. Only 'string' has no binding, and HttpContextBase has a binding that is a bit different:

kernel.Bind<HttpContextBase>().ToMethod(context => new HttpContextWrapper(new HttpContext(new MyHttpRequest("", "", "", null, new StringWriter()))));

and MyHttpRequest is defined as follows:

public class MyHttpRequest : SimpleWorkerRequest
{
    public string UserHostAddress;
    public string RawUrl;

    public MyHttpRequest(string appVirtualDir, string appPhysicalDir, string page, string query, TextWriter output)
    : base(appVirtualDir, appPhysicalDir, page, query, output)
    {
        this.UserHostAddress = "127.0.0.1";
        this.RawUrl = null;
    }
}
Daimyo answered 20/11, 2012 at 3:57 Comment(14)
Could you show the target MyService constructor? The specified name must equal the name of the cinstructor argument.Shwalb
@KonstantinVasilcov See my update above. I juste added the code for my constructor.Feint
Do you have bindings for each of those interfaces?Shwalb
@KonstantinVasilcov I doubled checked and Yes I do. They all look like kernel.Bind<IEmailService>().To<EmailService>(); except for the HttpContextBase binding, which I am now showing in the Update section of my question above.Feint
As for me string argument binding works well. I couldn't bind HttpContextBase to method...I only managed to make everything work having changed HttpContextBase binding to this kernel.Bind<IServiceProvider>().ToMethod(...)Shwalb
@KonstantinVasilcov For a test, I just created another constructor without the testEmail parameter, and I decorated it with the [Ninject.Inject] attribute. Now it is working, except for other bugs that are further down the road, but the injection is working, even for HttpContextBase for me. Still, I would like to be able to get this testEmail parameter working at some point.Feint
Actually I'm using Ninject 3.0, probably this could cause some differences...Well, did you try to remove HttpContextBase and use the string argument?Shwalb
@KonstantinVasilcov I am using Ninject v3.0.1.10. I haven't tried removing HttpContextBase from the constructor. This will be the next thing I try.Feint
Are you sure that you have only one Kernel? Is it the same kernel where you set WithConstructorArgument and from where call var myService = kernel.Get<MyService>(); (you can check during debugging with the GetHascode() method)?Weevil
@KonstantinVasilcov I tried removing HttpContextBase from the constructor, and making testEmail the first parameter of the constructor instead of the last, but I am still getting the same error.Feint
@Weevil I just checked, and yes, I have only one kernel. I set various breakpoints and everywhere, kernel.GetHashcode() is giving me the same number. Thanks for letting me know how to check this.Feint
I think you are Get<> the wrong type... try with var myService = kernel.Get<IMyService>(); notice the IMyServiceWeevil
@Weevil That was it. I was passing the class instead of the interface to kernel.Get<>(). Thank you so much Nemesv! You should post re-post what you wrote as an answer so I can mark it as the solution to my question.Feint
Yes indeed, it was a very strange manifestation of a really simple problem.Weevil
W
40

With the statement:

var myService = kernel.Get<MyService>();

You are trying the resolve MyService and because the MyService type is not registered in your kernel Ninject will treat it as a self bound type.

So it won't use your WithConstructorArgument to resolve the "testEmail" because it will be only used with Bind<IMyService>() that is why you're getting the exception.

So if you have registered your MyService with:

string testEmail = "[email protected]";
kernel.Bind<IMyService>().To<MyService>()
      .WithConstructorArgument("testEmail", testEmail);

Then you should resolve it through the registered interface (IMyService):

var myService = kernel.Get<IMyService>();
Weevil answered 20/11, 2012 at 16:41 Comment(1)
Also, make sure the class injecting wasn't marked abstract accidentally ;). The error won't tell you.Grearson
V
2

While nemesv has the correct response, I ran into the same error and the solution for me was a rogue DLL in my /bin. I had refactored and removed/moved some classes which were still present in my old DLL. Solution- remove the old DLL.

Volz answered 19/7, 2016 at 18:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.