Friday, October 26, 2012

Writing custom Windsor Controller Factory in ASP.NET MVC

Let's say we use Windsor IoC container in our ASP.NET MVC3 application. We registered some dependencies in Global.asax bootstrapper and now we need somehow to resolve them in our controller.

Of course we can do this:
 public class MyController : BaseController  
 {   
   private IFoo _dependency;   
   public MyController()  
   {  
    _dependency = Container.Resolve<IFoo>();   
   }  
   public ActionResult Index()  
   {   
    _dependency.DoSomething(); 
     ... 
   }  
 }  

But it is not good solution, because now we have dependency on IoC container itself in our controller. Besides, using any forms of Service Locator is a bad design practice.

More elegant solution is to write custom Controller Factory(in our case it is Windsor Controller Factory):
 public class WindsorControllerFactory : DefaultControllerFactory  
 {  
   private readonly IKernel _kernel;  
   public WindsorControllerFactory(IKernel kernel)  
   {  
    _kernel = kernel;  
   }  
   public override void ReleaseController(IController controller)  
   {  
    _kernel.ReleaseComponent(controller);  
   }  
   protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)  
   {  
    if (controllerType == null)  
    {  
      throw new HttpException(404, string.Format("The controller for path '{0}' could not be found.", requestContext.HttpContext.Request.Path));  
    }  
    var controller = (Controller)_kernel.Resolve(controllerType);      
    return controller;  
   }  
 }  

And then to register this factory as default Controller Factory in our MVC application in Global.asax:
 Container = new WindsorContainer();  
 ControllerBuilder.Current.SetControllerFactory(new WindsorControllerFactory(container.Kernel));  

Now we can do elegant dependency injections in our controller's constructor without references on specific IoC(in our case it's Castle Windsor):
 public class MyController : BaseController  
 {  
   private IFoo _dependency;  
   public MyController(IFoo dependency)  
   {  
    _dependency = dependency;  
   }  
   public ActionResult Index()  
   {  
    _dependency.DoSomething();
     ...
   }  
 }  

No comments:

Post a Comment