2
votes

I am trying to use Bootstrapper with Ninject. I have installed Ninject.MVC3 to initialize my Ninject container from nuget and I have created a test module like this:

public class TestNinjectModule : NinjectModule
{
    public override void Load()
    {
        Bind<DBEntities>().ToSelf().InRequestScope();
        Bind(typeof(IGenericRepository<>))
              .To(typeof(GenericRepository<>)).InRequestScope();
        Bind<ISystemRepository>().To<SystemRepository>().InRequestScope();
        Bind<IUnitOfWork>().To<UnitOfWork>();
    }
}

I have also included the Start() call in my Global.asax.cs

public class MvcApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();

        WebApiConfig.Register(GlobalConfiguration.Configuration);
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);

        Bootstrapper.With.Ninject().Start();
        Bootstrapper.With.AutoMapper().Start();
    }
}

However I still get an ActivationException from Ninject when a controller with dependency is called, signalling my TestNinjectModule.Load() method was not called. How can I solve that?

Exception Message:

Error activating IUnitOfWork No matching bindings are available, and the type is not self-bindable. Activation path: 2) Injection of dependency IUnitOfWork into parameter unitOfWork of constructor of type > TreasurySystemController 1) Request for SystemController

Suggestions: 1) Ensure that you have defined a binding for IUnitOfWork. 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.

Stack Trace:

at Ninject.KernelBase.Resolve(IRequest request) in c:\Projects\Ninject\ninject\src\Ninject\KernelBase.cs:line 359 at Ninject.Planning.Targets.Target1.GetValue(Type service, IContext parent) in c:\Projects\Ninject\ninject\src\Ninject\Planning\Targets\Target.cs:line 197 at Ninject.Planning.Targets.Target1.ResolveWithin(IContext parent) in c:\Projects\Ninject\ninject\src\Ninject\Planning\Targets\Target.cs:line 165 at Ninject.Activation.Providers.StandardProvider.GetValue(IContext context, ITarget target) in c:\Projects\Ninject\ninject\src\Ninject\Activation\Providers\StandardProvider.cs:line 114 at Ninject.Activation.Providers.StandardProvider.<>c_DisplayClass4.b_2(ITarget target) in c:\Projects\Ninject\ninject\src\Ninject\Activation\Providers\StandardProvider.cs:line 96 at System.Linq.Enumerable.WhereSelectArrayIterator2.MoveNext() at System.Linq.Buffer1..ctor(IEnumerable1 source) at System.Linq.Enumerable.ToArray[TSource](IEnumerable1 source) at Ninject.Activation.Providers.StandardProvider.Create(IContext context) in c:\Projects\Ninject\ninject\src\Ninject\Activation\Providers\StandardProvider.cs:line 96 at Ninject.Activation.Context.Resolve() in c:\Projects\Ninject\ninject\src\Ninject\Activation\Context.cs:line 157 at Ninject.KernelBase.<>c_DisplayClass10.b_c(IBinding binding) in c:\Projects\Ninject\ninject\src\Ninject\KernelBase.cs:line 386 at System.Linq.Enumerable.WhereSelectEnumerableIterator2.MoveNext() at System.Linq.Enumerable.SingleOrDefault[TSource](IEnumerable1 source) at Ninject.Web.Mvc.NinjectDependencyResolver.GetService(Type serviceType) in c:\Projects\Ninject\ninject.web.mvc\mvc3\src\Ninject.Web.Mvc\NinjectDependencyResolver.cs:line 56 at System.Web.Mvc.DefaultControllerFactory.DefaultControllerActivator.Create(RequestContext requestContext, Type controllerType)

1
'ActivationException' ... 'when a controller with dependency is called'... what exception ? what 'called' ? I think you might be jumping to premature conclusions. What happens if you put a breakpoint on Load ? What do you see when you examine the Kernel at the point at which the Activation is failing?Ruben Bartelink
@RubenBartelink ActivationException is the exception thrown by Ninject when it cannot resolve the dependency. When I put breakpoints in my Application_Start() and CreateKernel() (in NinjectWebCommon class, created by installing Ninject.MVC3 nuget package), there are two kernels being created, and only the one without my bindings was activated to resolve dependencies. That's why I am getting the exceptionrexcfnghk
TL;DR - you didn't answer my questions which is why nobody has answered your question yet. I know what an ActivationException is and lots of others do do; my point is that a full StackTrace (it doesn't have to be 20 pages) and the Message adds a lot. The 2 kernels are for 2 HttpApplications. Is your Load() being hit? Is the failing resolve [that we dont have a stacktrace for] (when you tell the debugger to break on First Chance) happening against a Kernel with or without your bindings.Ruben Bartelink
Updated with exception message and stack trace. My Load() method was hit but as I said it seems I have created two Ninject kernels in my application (not sure if that's correct or not) and only one of them is used to resolve my dependencies, which doesn't have the NinjectModule in it.rexcfnghk
+1 Much better. There should be def 2 HttpApplications and associated kernels unless I'm mistaken (it's possible to share them but def not a good idea). Stack traces from Kernel ctor should let you know who is creating the other Kernel without the Load of your Module?Ruben Bartelink

1 Answers

3
votes

I have found a solution. By changing the implementation of NinjectWebCommon to:

public static class NinjectWebCommon 
{
    private static readonly Bootstrapper bootstrapper = new Bootstrapper();
    public static IKernel Kernel { get; private set; } // Expose the kernel through a property

    /// <summary>
    /// Starts the application
    /// </summary>
    public static void Start() 
    {
        DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
        DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
        bootstrapper.Initialize(CreateKernel);
    }

    /// <summary>
    /// Stops the application.
    /// </summary>
    public static void Stop()
    {
        bootstrapper.ShutDown();
    }

    /// <summary>
    /// Creates the kernel that will manage your application.
    /// </summary>
    /// <returns>The created kernel.</returns>
    private static IKernel CreateKernel()
    {
        var kernel = new StandardKernel();
        kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
        kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();

        return Kernel = kernel;
    }
}

Then in Global.asax.cs:

public class MvcApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();

        WebApiConfig.Register(GlobalConfiguration.Configuration);
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);

        Bootstrapper.With.AutoMapper().Start();
        Bootstrapper.With.Ninject()
            .WithContainer(NinjectWebCommon.Kernel) // Use the kernel inside NinjectWebCommon instead of creating a new one
            .Start();
    }
}

Then all classes deriving from NinjectModule will have their Load() methods called.