23

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 = "test@example.com";
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;
    }
}
Steven
  • 166,672
  • 24
  • 332
  • 435
Jean-François Beauchamp
  • 5,485
  • 8
  • 43
  • 77
  • Could you show the target MyService constructor? The specified name must equal the name of the cinstructor argument. – horgh Nov 20 '12 at 04:06
  • @KonstantinVasilcov See my update above. I juste added the code for my constructor. – Jean-François Beauchamp Nov 20 '12 at 04:32
  • Do you have bindings for each of those interfaces? – horgh Nov 20 '12 at 04:44
  • @KonstantinVasilcov I doubled checked and Yes I do. They all look like kernel.Bind().To(); except for the HttpContextBase binding, which I am now showing in the Update section of my question above. – Jean-François Beauchamp Nov 20 '12 at 04:51
  • 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().ToMethod(...)` – horgh Nov 20 '12 at 05:09
  • @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. – Jean-François Beauchamp Nov 20 '12 at 05:15
  • 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? – horgh Nov 20 '12 at 05:21
  • @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. – Jean-François Beauchamp Nov 20 '12 at 06:01
  • 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();` (you can check during debugging with the GetHascode() method)? – nemesv Nov 20 '12 at 06:11
  • @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. – Jean-François Beauchamp Nov 20 '12 at 16:23
  • @nemesv 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. – Jean-François Beauchamp Nov 20 '12 at 16:25
  • I think you are `Get<>` the wrong type... try with `var myService = kernel.Get();` notice the `IMyService` – nemesv Nov 20 '12 at 16:28
  • 1
    @nemesv 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. – Jean-François Beauchamp Nov 20 '12 at 16:40
  • Yes indeed, it was a very strange manifestation of a really simple problem. – nemesv Nov 20 '12 at 16:43

2 Answers2

37

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 = "test@example.com";
kernel.Bind<IMyService>().To<MyService>()
      .WithConstructorArgument("testEmail", testEmail);

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

var myService = kernel.Get<IMyService>();
nemesv
  • 138,284
  • 16
  • 416
  • 359
  • Also, make sure the class injecting wasn't marked abstract accidentally ;). The error won't tell you. – jwize Jul 17 '19 at 16:28
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.

jrap
  • 335
  • 2
  • 11