Ninject 2 + ASP.NET MVC 2 Types of Binding from External Assemblies
I am just trying to get started with Ninject 2 and ASP.NET MVC 2. I followed this tutorial http://www.craftyfella.com/2010/02/creating-aspnet-mvc-2-controller.html to create a Factory controller with using Ninject and bind the first abstract to a concrete implementation. Now I want to load a repository type from another assembly (where my specific SQL repos are located) and I just can't get it to work. Here's my code:
Global.asax.cs
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes);
ControllerBuilder.Current.SetControllerFactory(new MyControllerFactory());
}
Factory Controller:
public class Kernelhelper
{
public static IKernel GetTheKernel()
{
IKernel kernel = new StandardKernel();
kernel.Load(System.Reflection.Assembly.Load("MyAssembly"));
return kernel;
}
}
public class MyControllerFactory : DefaultControllerFactory
{
private IKernel kernel = Kernelhelper.GetTheKernel();
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
return controllerType == null ? null : (IController)kernel.Get(controllerType);
}
}
There is a module in "MyAssembly":
public class ExampleConfigModule : NinjectModule
{
public override void Load()
{
Bind<Domain.CommunityUserRepository>().To<SQLCommunityUserRepository>();
}
}
Now that I just bumped into the MockRepository object at my entry point, it works fine, the controller that needs the repository works fine. Kernel .Load (System.Reflection.Assembly.Load ("MyAssembly")); also does its job and registers the module, but as soon as I call the controller that needs the repository, I get an ActivationException from Ninject:
There are no matching bindings and the type is not self-switching. Activation path: 2) Injection of CommunityUserRepository dependency into the _rep parameter of the constructor of type AccountController 1) Request for AccountController
Can anyone give me a best practice example for binding types from external assemblies (which is really an important aspect of Dependency Injection)? Thank!
source to share
Ok, I did some refactorings and now it works for me. I will post the code for my Global.asax once everything happens. I am using the latest Ninject 2 Build with the latest Ninject.Web.Mvc for MVC 2.
public class MvcApplication : NinjectHttpApplication
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = "" } // Parameter defaults
);
}
protected override void OnApplicationStarted()
{
AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes);
RegisterAllControllersIn(System.Reflection.Assembly.GetExecutingAssembly());
}
protected override Ninject.IKernel CreateKernel()
{
var kernel = new StandardKernel();
kernel.Load(new ExampleConfigModule());
return kernel;
}
}
public class ExampleConfigModule : Ninject.Modules.NinjectModule
{
public override void Load()
{
string connectionString =
ConfigurationManager.ConnectionStrings
["ConnectionString1"].ConnectionString;
string communityUserRepTypeName =
ConfigurationManager.AppSettings
["CommunityUserRepositoryType"];
var communityUserRepositoryType =
Type.GetType(communityUserRepTypeName, true);
Bind<Domain.CommunityUserRepository>().To(communityUserRepositoryType).WithConstructorArgument("conString",connectionString);
}
}
As you can see, I got rid of my ControllerFactory inherited from NinjectHttpApplication and loaded and associated the external assembly type with the module. Now there might be a better way without specifying the type as a string in the config file, perhaps you could declare the module in an external assembly and let Ninject automatically load it from there, but I still need to pass the connection string down to the implementation-specific constructor. Maybe someone has an idea, but this works great for now.
source to share