No matching bindings are available, and the type is not self-bindable in Ninject
Asked Answered
T

2

10

I am using Ninjec, Ninject.Web.MVC and Ninject.Web.Common

When I start my mvc application I get this binding error:

What do I wrong in my binding?

Error activating DbConnection

No matching bindings are available, and the type is not self-bindable.

Activation path:

4) Injection of dependency DbConnection into parameter existingConnection of constructor of type DbContext

3) Injection of dependency DbContext into parameter dbContext of constructor of type GenericRepository{User}

2) Injection of dependency IGenericRepository{User} into parameter repo of constructor of type HomeController

1) Request for HomeController

Suggestions:

1) Ensure that you have defined a binding for DbConnection.

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.

public interface IGenericRepository<T> where T : class
{
}

public class GenericRepository<T> : IGenericRepository<T> where T : class
{
        public GenericRepository(TLPContext dbContext)
        {
            DbContext = dbContext;
        }

        protected TLPContext DbContext { get; private set; }
}

[assembly: WebActivator.PreApplicationStartMethod(typeof(TLP.App_Start.NinjectWebCommon), "Start")]
[assembly: WebActivator.ApplicationShutdownMethodAttribute(typeof(TLP.App_Start.NinjectWebCommon), "Stop")]

namespace TLP.App_Start
{
    using Microsoft.Web.Infrastructure.DynamicModuleHelper;
    using Ninject;
    using Ninject.Web.Common;
    using System;
    using System.Web;
    using TLP.DataAccess;
    using TLP.DataAccess.Contract;
    using TLP.DataAccess.Implementation;

    public static class NinjectWebCommon
    {
        private static readonly Bootstrapper bootstrapper = new Bootstrapper();
        public static void Start()
        {
            DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
            DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
            bootstrapper.Initialize(CreateKernel);
        }

        public static void Stop()
        {
            bootstrapper.ShutDown();
        }

        private static IKernel CreateKernel()
        {
            var kernel = new StandardKernel();
            kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
            kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
            kernel.Bind<TLPContext>();
            kernel.Bind(typeof(IGenericRepository<>)).To(typeof(GenericRepository<>));
            return kernel;
        }
    }
}


[DbModelBuilderVersion(DbModelBuilderVersion.V5_0)]
    public class TLPContext : DbContext
    {
        public TLPContext()
            : base("DefaultConnection")
        {
            // We do not want implicit uncontrollable lazy loading, instead we use the explicit Load method
            this.Configuration.LazyLoadingEnabled = false;
        }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();

            // Primary key
            modelBuilder.Entity<User>().HasKey(p => p.UserId);
            modelBuilder.Entity<User>().Property(p => p.FirstName).HasMaxLength(30).IsRequired();
            modelBuilder.Entity<User>().Property(p => p.RegisteredAt).IsRequired();
        }

        public DbSet<User> Users { get; set; }
    }
Tore answered 12/2, 2013 at 19:46 Comment(0)
M
11

Ninjects looks for constructors in the following order:

  1. Constructors marked with [Inject]
  2. Construtors with the most parameter
  3. Default contructor

In your case your TLPContext constructor is not marked with [Inject] so the 2. rules applies and Ninject will try to resolve the base class contructor and then throws the exception.

So you can solve this by marking your constructor with the InjectAttribute

[Inject]
public TLPContext()
   : base("DefaultConnection")
{
   this.Configuration.LazyLoadingEnabled = false;
}

Or you can specify the constructor with the ToConstructor method when registering your TLPContext:

kernel.Bind<TLPContext>().ToConstructor(_ => new TLPContext());
Mike answered 12/2, 2013 at 20:18 Comment(7)
Thats odd. I have never used .ToConstructor() to get injection via constructor. I do not want to introduce Ninject into my DataAccess project. I tried your code and it change nothing. But what I forgot last time: NinjectDependencyResolver.cs source not found I get also... Any clue? Ah now I get it. I use a WebApi project instead of the mvc only before. Seems Ninject works here differently...Tore
What do you mean on "NinjectDependencyResolver.cs source not found"? How did you installed Ninject in your project with nuget?Mike
And with the usage of the ToConstructor() do you still get the exact same error message: "4) Injection of dependency DbConnection into parameter existingConnection of constructor of type DbContext"? Are you sure that your app is correctly recompiled. Can you try to clean and rebuild your solution?Mike
Thats odd. Now I rebuild it and the ToConstructor() works. The repo is injected into the HomeController. But when I use my old method without ToConstructor I get this: BindingConfiguration.cs is not found ??Tore
I'm glad that your original issue is solved. About the strange error: BindingConfiguration.cs is the part of the Ninject source. So I don't know why VS complains about it... Are you using resharper and using its source decompilation feature? Because sometimes the decompiled files confuses VS. You can try to close all open files and reopen the solution.Mike
No resharper I use. Maybe the ToConstructor() works because I do not bind the TLPContext in the way I always did former times: kernel.Bind<ITLPContext>().To<TLPContext>(). Now with TLPContext there is no interface its just binding to itself. Is this the reason I need the ToConstructor() ? I really never have used that before just to bind to a constructor parameter.Tore
Yes, you need to use ToConstructor otherwise because your TLPContext has multiple contructors because of its base class DbContext Ninject cannot pick the right constructor so you got the exception.Mike
S
4

I used to have similar problem. I was using Ninject MVC and I tried to instantiate the kernel using the new StandardKernel ctor, and it did't work.

My problem was the point 3 that @Elisa mentioned earlier: Ensure you have not accidentally created more than one kernel.

I solved it by using bootstrapper.Kernel instead.

Silicium answered 12/2, 2014 at 15:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.