Dependency injection in constructor of controller with using a ControllerFactory in ASP.NET MVC 5 - asp.net-mvc

I'm developing ASP.NET MVC 5 app. I need to use parameters in controller's constructor. DefaultControllerFactory can't resolve it and i inherited from it my own ControllerFactory:
public class ControllerFactoryProvider : DefaultControllerFactory
{
public IController CreateController(System.Web.Routing.RequestContext requestContext, string controllerName)
{
string controllerType = string.Empty;
IController controller = null;
// Read Controller Class & Assembly Name from Web.Config
controllerType = ConfigurationManager.AppSettings[controllerName];
if (controllerType == null)
throw new ConfigurationErrorsException("Assembly not configured for controller " + controllerName);
// Create Controller Instance
IDataTransmitter _dataTransmitter = new DataTransmitter();
controller = Activator.CreateInstance(Type.GetType(controllerType), _dataTransmitter) as IController;
return controller;
}
public void ReleaseController(IController controller)
{
//This is a sample implementation
//If pooling is used to write code to return the object to pool
if (controller is IDisposable)
{
(controller as IDisposable).Dispose();
}
controller = null;
}
}
I registered it in Global.asax:
ControllerBuilder.Current.SetControllerFactory(new
ControllerFactoryProvider());
But when i run my app it whatever use DefaultControllerFactory didn't see constructor with parameters.
Where can i have an error?

As I said in the comments, there is no need to override your controller factory. You just need to plug in your preferred dependency injection container.
I haven't had the opportunity to work with every dependency injection containers for .net but I'll try to give an objective answer.
Ninject
To set up Ninject in an asp.net Mvc 5 project is very straight forward.
Installing the nuget package
There's a very handy nuget package called Ninject.MVC5.
You can install it:
Using the manage nuget packages dialogue, or
By running Install-Package Ninject.MVC5 in the package manager console.
After installing Ninject.MVC5 you will see a new file in your solution in App_Start/ called NinjectWebCommon.cs. Here you can see what the contents of that file will end up being.
Wiring up your dependencies
Now that the package is installed you want to register your denpencies using ninject's api.
Let's say you have an IFoo interface and its implementation Foo
public interface IFoo
{
int Bar()
}
public class Foo : IFoo
{
public int Bar()
{
throw new NotImplementedException();
}
}
In your NinjectWebCommon class you're going to tell ninject how to resolve an IFoo interface:
/// <summary>
/// Load your modules or register your services here!
/// </summary>
/// <param name="kernel">The kernel.</param>
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IFoo>().To<Foo>();
}
Keep in mind that by default Ninject has implicit self binding of concrete types, that means that
If the type you’re resolving is a concrete type (like Foo above), Ninject will automatically create a default association via a mechanism called implicit self binding. It’s as if there’s a registration like this:
Bind<Foo>().To<Foo>();

Related

How can I get started with ASP.NET (5) Core and Castle Windsor for Dependency Injection?

Background:
I've used Castle Windsor with Installers and Facilities according to the Castle Windsor tutorial with earlier versions of MVC (pre-6) and WebAPI.
ASP.NET (5) Core has included some Dependency Injection support but I still haven't figured out exactly how to wire it up, and the few samples I have found look a lot different than how I've used it before (with the installers/facilities). Most examples predate ASP.NET (5) cores recent release and some seem to have outdated information.
It seems to have changed quite radically from the previous versions composition root setup, and not even Microsoft.Framework.DependencyInjection.ServiceProvider can resolve all of the dependencies when I set it as the Castle Windsor DI fallback. I'm still digging into the details but there isn't much up to date information.
My attempt to use Castle Windsor for DI
I've found an adapter like this: Github Castle.Windsor DI container.
Startup.cs
private static IWindsorContainer container;
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerfactory)
{
container = new WindsorContainer();
app.UseServices(services =>
{
// ADDED app.ApplicationServices FOR FALLBACK DI
container.Populate(services, app.ApplicationServices);
container.BeginScope();
return container.Resolve<IServiceProvider>();
});
// ... default stuff
WindsorRegistration.cs
I added a few lines to add a Castle Windsor ILazyComponentLoader fallback.
using Castle.MicroKernel.Lifestyle;
using Castle.MicroKernel.Registration;
using Castle.MicroKernel.Resolvers.SpecializedResolvers;
using Castle.Windsor;
using Microsoft.Framework.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Reflection;
namespace Notes.Infrastructure
{
/// <summary>
/// An adapted current autofac code to work with Castle.Windsor container.
/// https://github.com/aspnet/Home/issues/263
/// </summary>
public static class WindsorRegistration
{
public static void Populate(
this IWindsorContainer container,
IEnumerable<IServiceDescriptor> descriptors,
IServiceProvider fallbackProvider // ADDED FOR FALLBACK DI
)
{
// ADDED FOR FALLBACK DI
// http://davidzych.com/2014/08/27/building-the-castle-windsor-dependency-injection-populator-for-asp-net-vnext/
// Trying to add a fallback if Castle Windsor doesn't find the .NET stuff
var fallbackComponentLoader = new FallbackLazyComponentLoader(fallbackProvider);
container.Register(Component.For<ILazyComponentLoader>().Instance(fallbackComponentLoader));
// Rest as usual from the Github link
container.Register(Component.For<IWindsorContainer>().Instance(container));
container.Register(Component.For<IServiceProvider>().ImplementedBy<WindsorServiceProvider>());
container.Register(Component.For<IServiceScopeFactory>().ImplementedBy<WindsorServiceScopeFactory>());
container.Kernel.Resolver.AddSubResolver(new CollectionResolver(container.Kernel));
Register(container, descriptors);
}
private static void Register(
IWindsorContainer container,
IEnumerable<IServiceDescriptor> descriptors)
{
foreach (var descriptor in descriptors)
{
if (descriptor.ImplementationType != null)
{
// Test if the an open generic type is being registered
var serviceTypeInfo = descriptor.ServiceType.GetTypeInfo();
if (serviceTypeInfo.IsGenericTypeDefinition)
{
container.Register(Component.For(descriptor.ServiceType)
.ImplementedBy(descriptor.ImplementationType)
.ConfigureLifecycle(descriptor.Lifecycle)
.OnlyNewServices());
}
else
{
container.Register(Component.For(descriptor.ServiceType)
.ImplementedBy(descriptor.ImplementationType)
.ConfigureLifecycle(descriptor.Lifecycle)
.OnlyNewServices());
}
}
else if (descriptor.ImplementationFactory != null)
{
var service1 = descriptor;
container.Register(Component.For(descriptor.ServiceType)
.UsingFactoryMethod<object>(c =>
{
var builderProvider = container.Resolve<IServiceProvider>();
return
service1.ImplementationFactory(builderProvider);
})
.ConfigureLifecycle(descriptor.Lifecycle)
.OnlyNewServices());
}
else
{
container.Register(Component.For(descriptor.ServiceType)
.Instance(descriptor.ImplementationInstance)
.ConfigureLifecycle(descriptor.Lifecycle)
.OnlyNewServices());
}
}
}
private static ComponentRegistration<object> ConfigureLifecycle(
this ComponentRegistration<object> registrationBuilder,
LifecycleKind lifecycleKind)
{
switch (lifecycleKind)
{
case LifecycleKind.Singleton:
registrationBuilder.LifestyleSingleton();
break;
case LifecycleKind.Scoped:
registrationBuilder.LifestyleScoped();
break;
case LifecycleKind.Transient:
registrationBuilder.LifestyleTransient();
break;
}
return registrationBuilder;
}
private class WindsorServiceProvider : IServiceProvider
{
private readonly IWindsorContainer _container;
public WindsorServiceProvider(IWindsorContainer container)
{
_container = container;
}
public object GetService(Type serviceType)
{
return _container.Resolve(serviceType);
}
}
private class WindsorServiceScopeFactory : IServiceScopeFactory
{
private readonly IWindsorContainer _container;
public WindsorServiceScopeFactory(IWindsorContainer container)
{
_container = container;
}
public IServiceScope CreateScope()
{
return new WindsorServiceScope(_container);
}
}
private class WindsorServiceScope : IServiceScope
{
private readonly IServiceProvider _serviceProvider;
private readonly IDisposable _scope;
public WindsorServiceScope(IWindsorContainer container)
{
_scope = container.BeginScope();
_serviceProvider = container.Resolve<IServiceProvider>();
}
public IServiceProvider ServiceProvider
{
get { return _serviceProvider; }
}
public void Dispose()
{
_scope.Dispose();
}
}
}
}
First hiccup and resolution attempt
From that example I was getting:
An exception of type 'Castle.MicroKernel.ComponentNotFoundException' occurred in Castle.Windsor.dll but was not handled in user code
Additional information: No component for supporting the service Microsoft.Framework.Runtime.IAssemblyLoaderEngine was found
It wasn't available looking in the debugger at the Castle Fallback - Microsoft.Framework.DependencyInjection.ServiceProvider (table of services).
From http://davidzych.com/tag/castle-windsor/ I have tried to add a Fallback since Windsor couldn't resolve all of the ASP.NET dependencies.
FallbackLazyComponentLoader.cs
/// <summary>
/// https://github.com/davezych/DependencyInjection/blob/windsor/src/Microsoft.Framework.DependencyInjection.Windsor/FallbackLazyComponentLoader.cs
/// </summary>
public class FallbackLazyComponentLoader : ILazyComponentLoader
{
private IServiceProvider _fallbackProvider;
public FallbackLazyComponentLoader(IServiceProvider provider)
{
_fallbackProvider = provider;
}
public IRegistration Load(string name, Type service, IDictionary arguments)
{
var serviceFromFallback = _fallbackProvider.GetService(service);
if (serviceFromFallback != null)
{
return Component.For(service).Instance(serviceFromFallback);
}
return null;
}
}
It was seemingly necessary (to inject all the .NET dependencies)
I could comment out startup.cs app.UseBrowserLink(); to get rid of the IAssemblyLoaderEngine exception.
if (string.Equals(env.EnvironmentName, "Development", StringComparison.OrdinalIgnoreCase))
{
//app.UseBrowserLink(); //
Now I run into an exception:
An exception of type 'System.Reflection.TargetInvocationException' occurred in mscorlib.dll but was not handled in user code
Trying to get the service: {Name = "IUrlHelper" FullName = "Microsoft.AspNet.Mvc.IUrlHelper"}
public IRegistration Load(string name, Type service, IDictionary arguments)
{
var serviceFromFallback = _fallbackProvider.GetService(service);
How to move forward?
What is wrong with this attempt to wire up Castle Windsor DI into ASP.NET (5) Core?
For now I don't think you can use Castle Windsor Container as the DI container because Windsor doesn't support the new DNVM. But AutoFac does and they follow the same rule.
In the Startup.cs there is a ConfigureServices method whose return type is void. You can change the return type to ISerivceProvider and return a concrete IServiceProvider, the system will use the new IServiceProvider as the default DI container. Below is the AutoFac example.
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.Configure<AppSettings>(Configuration.GetSubKey("AppSettings"));
services.AddMvc();
var builder = new ContainerBuilder();
AutofacRegistration.Populate(builder, services);
var container = builder.Build();
return container.Resolve<IServiceProvider>();
}
The other DI adapters also implemented the similar interfaces. You can try yourself, but note AutoFac is in beta5 now so you need to make some adjustment to make your application run.
Hope this helps
There is a lot going on in your question, and to be honest I don't understand all of it.
However, there is a working Castle Windsor composition root in MvcSiteMapProvider that you are welcome reverse-engineer. Follow these steps to get a working composition root demo project for Windsor:
Create a new MVC 5 project.
Install MvcSiteMapProvider.MVC5.DI.Windsor.
Analyze the following files for the basic structure:
/App_Start/DIConfig.cs
/App_Start/CompositionRoot.cs
/DI/InjectableControllerFactory.cs
/DI/Windsor/WindsorDependencyInjectionContainer.cs
/DI/Windsor/Installers/MvcInstaller.cs
/DI/Windsor/Installers/MvcSiteMapProviderInstaller.cs
Once you have this working configuration, you can then refactor it and add to it to suit your application's needs.
As I recall, there weren't any changes required to make the MVC 4 DI configuration work with MVC 5. So, the problem you are running into is most likely one of the following:
You are using a 3rd party DI component that is not compatible with MVC 5.
You are using DependencyResolver, and your configuration doesn't include the necessary code to resolve the dependencies of MVC 5.
You are using advanced features of Castle Windsor that we are not using, and have them misconfigured in some way.
ControllerFactory vs DependencyResolver
Do note that according to Dependency Injection in .NET by Mark Seemann (which I highly recommend), it is ill-advised to use IDependencyResolver with Castle Windsor because it guarantees resource leaks. In fact, this is probably the most compelling argument that he makes for his reasoning for declaring service locator as anti-pattern.
The recommended approach is to use IControllerFactory as the integration point into MVC, which implements a ReleaseController method to solve this issue.
So looking at your code, literally all of it can be replaced by Castle.Windsor.MsDependencyInjection library.
Add Castle.Windsor.MsDependencyInjection to your project then use like so:
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddMvc();
// Normal component registration can go here...
return WindsorRegistrationHelper.CreateServiceProvider(yourWindsorContainer, services);
}

How does ASP.NET MVC know what controller constructor to call?

I'm currently starting ASP.NET MVC 4 and in the book I am reading, the author introduced Ninject for dependency injection. He created a custom dependency resolver (which I don't fully understand how it works, but I think it's use is to easily manage dependency resolution).
Here is the controller code:
public class HomeController : Controller
{
private Product[] products = {
new Product {Name = "Kayak", Category = "Watersports", Price = 275M},
new Product {Name = "Lifejacket", Category = "Watersports", Price = 48.95M},
new Product {Name = "Soccer ball", Category = "Soccer", Price = 19.50M},
new Product {Name = "Corner flag", Category = "Soccer", Price = 34.95M}
};
private IValueCalculator calc;
public HomeController(IValueCalculator calcParam)
{
calc = calcParam;
}
public ActionResult Index()
{
ShoppingCart cart = new ShoppingCart(calc) { Products = products };
decimal totalValue = cart.CalculateProductTotal();
return View(totalValue);
}
}
And the custom dependency resolver:
public class NinjectDependencyResolver : IDependencyResolver
{
private IKernel kernel;
public NinjectDependencyResolver()
{
kernel = new StandardKernel();
AddBindings();
}
public object GetService(Type serviceType)
{
return kernel.TryGet(serviceType);
}
public IEnumerable<object> GetServices(Type serviceType)
{
return kernel.GetAll(serviceType);
}
private void AddBindings()
{
kernel.Bind<IValueCalculator>().To<LinqValueCalculator>();
}
}
In Application_Start(), the resolver was set:
DependencyResolver.SetResolver(new NinjectDependencyResolver());
Questions:
How did ASP.NET MVC knew what controller constructor to call? I assumed it was going to call the default constructor but there isn't one, I tried adding one, still the constructor with the parameter was called.
How did ASP.NET MVC passed the IValueCalculator to the constructor?
This is quote from documentation (https://github.com/ninject/ninject/wiki/Dependency-Injection-With-Ninject):
When asked to instantiate an object, Ninject will look at the type’s
available public constructors and pick the one with the most
parameters it knows how to resolve — or the parameterless one if there
aren’t any suitable ones (there’s an attribute that can be used to
override this – see Constructor injection for the nitty gritty).
and another quote from here (https://github.com/ninject/ninject/wiki/Injection-Patterns):
If a constructor has an [Inject] attribute, it is used (but if you
apply the attribute to more than one, Ninject will throw a
NotSupportedException at runtime upon detection).
If no constructors have an [Inject] attribute, Ninject will select the one with the most parameters that Ninject understands how
to resolve.
If no constructors are defined, Ninject will select the default parameterless constructor (assuming there is one).
And how did ASP.NET MVC passed the IValueCalculator to the constructor?
Whole MVC pipeline uses controller factories to build instance of specific controller. Controller factory uses DependencyResolver inside. That is why dependency resolver is registered at application start:
DependencyResolver.SetResolver(new NinjectDependencyResolver());
As I wrote earlier, Ninject knows how to find correct constructor and uses it to build instance. It finds this constructor:
public HomeController(IValueCalculator calcParam)
Here dependency resolver is used to find implementation of IValueCalculator, which was defined here:
private void AddBindings()
{
kernel.Bind<IValueCalculator>().To<LinqValueCalculator>();
}
Ninject here tries one again to find constructor for class LinqValueCalculator. If constructor had dependencies, they would be injected using the same mechanism.
How did ASP.NET MVC know...
It knows by asking the DependencyResolver. MVC will call GetService() when a controller must be created.
The default MVC resolver only handles parametersless constructors, but in your case you have assigned your custom resolver, where the GetService() call will be relayed to NInject's IKernel.TryGet(Type).
NInject will then search for the type HomeController and its constructors, and will find the one with the IValueCalculator parameter.
In the AddBindings() method you have instructed NInject to inject LinqValueCalculator every time a IValueCalculator is required, so it does that, instantiates the type using reflection and returns the initialized controller to MVC.

Hook Unity into Web API Filter Attributes

I have Unity running great for all the controllers in my ASP.NET Web API project - just using the default set up that comes out of the NuGet box. I have also managed to hook it up to MVC Filter Attributes - but can't seem to do the same for ASP.NET Web API filter attributes.
How to I extend this default implementation to inject a dependency into an ActionFilterAttribute, for example...
public class BasicAuthenticationAttribute : ActionFilterAttribute
{
[Dependency]
public IMyService myService { get; set; }
public BasicAuthenticationAttribute()
{
}
}
This filter is applied to controllers using attributes:
[BasicAuthentication]
I'm pretty sure I need to hook up the Unity container so it handles the creation of the attribute class, but need some clues about where to start as it does not use the same extensibility points as the MVC filters.
I just wanted to add, other things I have tried include service location rather than dependency injection, but the DependencyResolver you get back is not the same one you configure.
// null
var service = actionContext.Request.GetDependencyScope().GetService(typeof(IMyService));
Or
// null
var service = GlobalConfiguration.Configuration.DependencyResolver.GetService(typeof(IApiUserService));
The problem is that the Attribute class is created by .NET and not by the WebAPI framework.
Before reading farther, did you forget to configure your DependencyResolver with your IApiUserService?
(IUnityContainer)container;
container.RegisterType<IApiUserService, MyApiUserServiceImpl>();
...
var service = GlobalConfiguration.Configuration.DependencyResolver.GetService(typeof(IApiUserService));
I created an App_Start\UnityConfig class that holds my UnityContainer:
public class UnityConfig {
#region Unity Container
private static Lazy<IUnityContainer> container = new Lazy<IUnityContainer>(() => {
var container = new UnityContainer();
RegisterTypes(container);
return container;
});
/// <summary>
/// Gets the configured Unity container.
/// </summary>
public static IUnityContainer GetConfiguredContainer() {
return container.Value;
}
#endregion
public static void Configure(HttpConfiguration config) {
config.DependencyResolver = new UnityDependencyResolver(UnityConfig.GetConfiguredContainer());
}
/// <summary>Registers the type mappings with the Unity container.</summary>
/// <param name="container">The unity container to configure.</param>
/// <remarks>There is no need to register concrete types such as controllers or API controllers (unless you want to
/// change the defaults), as Unity allows resolving a concrete type even if it was not previously registered.</remarks>
private static void RegisterTypes(IUnityContainer container) {
// NOTE: To load from web.config uncomment the line below. Make sure to add a Microsoft.Practices.Unity.Configuration to the using statements.
// container.LoadConfiguration();
// TODO: Register your types here
// container.RegisterType<IProductRepository, ProductRepository>();
container.RegisterType<MyClass>(new PerRequestLifetimeManager(), new InjectionConstructor("connectionStringName"));
}
}
The UnityDependencyResolver and PerRequestLifetimeManager came from this blog post and Unity.WebApi (Project/Nuget Package) which I internalized. (since it's a bootstrap)
When I need to make use of the UnityContainer in my other code, I passed it into the constructor:
config.Filters.Add(new MyFilterAttribute(UnityConfig.GetConfiguredContainer()));

Best practice -- how to get back the internal binding from controller factory?

I am following "ASP.Net MVC 3" by Steven Sanderson and Adam Freeman, and at one point they define ControllerFactory. The exposed interface is for creating controllers, and what is injected into them (like classes providing data) is black box (for outside world).
I am at the point, that I don't really want to get any controller, but the binding set for controller -- namely class providing data.
I could add another method for controller factory (like GetBinding) and it would work, but would it be the right way to do it?
Just to focus on something. I have IDataProvider and two classes -- MockupProvider and ProviderForReal. I would like to set it once, that for now whenever I need IDataProvider I will get MockupProvider. This is set up (by me) in controller factory.
And I would like to retrieve what I set up in most elegant way, so I won't bind again interface-class again. Is adding such method -- GetBinding -- to controller factor a good pattern?
I am not constructing the controller, I need binding controllers use.
In other words...
There is controller factory. Inside there are defined some bindings. I have to use retrieve them (binding, not controller). Technically I could do this in several ways:
take a look at the code, look at specific binding, and use the the bound type (hardcoding it) somewhere else
add public method to controller factory GetBinding
...?
What is the right way?
Update
My controller factory:
public class NinjectControllerFactory : DefaultControllerFactory
{
private IKernel ninject_kernel;
public NinjectControllerFactory()
{
ninject_kernel = new StandardKernel();
AddBindings();
}
private void AddBindings()
{
ninject_kernel.Bind<IBookRepository>().To<DataManagement.Concrete.EFBookRepository>();
// ninject_kernel.Bind<IBookRepository>().ToConstant(DataManagement.Mocks.Mocks.BookRepository);
}
public T GetBinding<T>()
{
return ninject_kernel.Get<T>();
}
protected override IController GetControllerInstance(System.Web.Routing.RequestContext requestContext, Type controllerType)
{
if (controllerType == null)
return null;
else
return (IController)ninject_kernel.Get(controllerType);
}
}
I'm trying to answer your questions following the comments. If it won't be suitable for you I'm prepared to delete it.
So in my ASP.NET MVC applications I'm using ninject and its mvc extension to inject dependencies to my controllers (and underlying services and repositories).
Global.asax
public class MvcApplication : Ninject.Web.Mvc.NinjectHttpApplication
{
/// this is here only to see that NinjectHttpApplication uses its own ControllerFactory, which is supposed to create your controllers with dependencies injected
protected override Ninject.Web.Mvc.NinjectControllerFactory CreateControllerFactory()
{
return base.CreateControllerFactory();
}
protected override IKernel CreateKernel()
{
var kernel = new StandardKernel();
// here you can configure your bindings according to actual requirements
kernel.Bind<IDataProvider>().To<ProviderForReal>().InRequestScope();
kernel.Bind<IDataService>().To<RealDataService().InRequestScope();
return kernel;
}
}
Controller
public class MyController : Controller
{
private readonly IDataProvider dataService;
// i will get injected an IDataProvider according to my actual configuration
public MyController(IDataService dataService)
{
this.dataService = dataService;
}
}
IDataService
public class RealDataService: IDataService{
private readonly IDataProvider dataProvider;
public RealDataService(IDataProvider dataProvider){
this.dataProvider = dataProvider;
}
}
Update
You do not need to write your own controller factory. In the code above I have put my override of CreateControllerFactory method only to show that Ninject.Web.Mvc.NinjectHttpApplication implicitly overrides this method and uses its own NinjectControllerFactory implmentation which will resolve dependencies for you (even if that dependencies are indirect - as you can see in my updated code => Ninject will resolve it for you because it will see that MyController needs IDataService and will look into bindings and will see that there is binding to RealDataService, but it has only constructor with dependency on IDataProvider. So it will look again to bindings and will see that IDataProvider is bound to ProviderForReal than it will create ProviderForReal inject it to ReadDataService and than RealDataService to MyController).

One Controller is Sometimes Bound Twice with Ninject

I have the following NinjectModule, where we bind our repositories and business objects:
/// <summary>
/// Used by Ninject to bind interface contracts to concrete types.
/// </summary>
public class ServiceModule : NinjectModule
{
/// <summary>
/// Loads this instance.
/// </summary>
public override void Load()
{
//bindings here.
//Bind<IMyInterface>().To<MyImplementation>();
Bind<IUserRepository>().To<SqlUserRepository>();
Bind<IHomeRepository>().To<SqlHomeRepository>();
Bind<IPhotoRepository>().To<SqlPhotoRepository>();
//and so on
//business objects
Bind<IUser>().To<Data.User>();
Bind<IHome>().To<Data.Home>();
Bind<IPhoto>().To<Data.Photo>();
//and so on
}
}
And here are the relevant overrides from our Global.asax, where we inherit from NinjectHttpApplication in order to integrate it with Asp.Net Mvc (The module lies in a separate dll called Thing.Web.Configuration):
protected override void OnApplicationStarted()
{
base.OnApplicationStarted();
//routes and areas
AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes);
//Initializes a singleton that must reference this HttpApplication class,
//in order to provide the Ninject Kernel to the rest of Thing.Web. This
//is necessary because there are a few instances (currently Membership)
//that require manual dependency injection.
NinjectKernel.Instance = new NinjectKernel(this);
//view model factory.
NinjectKernel.Instance.Kernel.Bind<IModelFactory>().To<MasterModelFactory>();
}
protected override NinjectControllerFactory CreateControllerFactory()
{
return base.CreateControllerFactory();
}
protected override Ninject.IKernel CreateKernel()
{
var kernel = new StandardKernel();
kernel.Load("Thing.Web.Configuration.dll");
return kernel;
}
Now, everything works great, with one exception: For some reason, sometimes Ninject will bind the PhotoController twice. This leads to an ActivationException, because Ninject can't discern which PhotoController I want. This causes all requests for thumbnails and other user images on the site to fail.
Here is the PhotoController in it's entirety:
public class PhotoController : Controller
{
public PhotoController()
{
}
public ActionResult Index(string id)
{
var dir = Server.MapPath("~/" + ConfigurationManager.AppSettings["UserPhotos"]);
var path = Path.Combine(dir, id);
return base.File(path, "image/jpeg");
}
}
Every controller works in exactly the same way, but for some reason the PhotoController gets double-bound. Even then, it only happens occasionally (either when re-building the solution, or on staging/production when the app pool kicks in). Once this happens, it continues to happen until I redeploy without changing anything.
So...what's up with that?
As noted in the comments of your answer to another similar question, this was a race condition bug in Ninject 2.0, which was fixed in version 2.2. I can't find any release notes for Ninject, but it solved this exact problem for me.

Resources