I'm trying to setup Castle Windsor for Dependency Injection in Sitecore 8.2 Solution which is using Glass Mapper v4. As noted, Castle Windsor is no longer part of Glass Mapper, and thus not included. I added it manually, and have setup the Installer, the Windsor Controller Factory, and the Pipeline Initializer for Sitecore
The Windsor Controller Factory:
namespace Web.Plumbing
{
public class WindsorControllerFactory : DefaultControllerFactory
{
private readonly IKernel kernel;
public WindsorControllerFactory(IKernel kernel)
{
this.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));
}
return (IController)kernel.Resolve(controllerType);
}
}
}
The Installer:
namespace Web.Installers
{
public class ControllersInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
Sitecore.Diagnostics.Log.Info("Windsor installer got registered", this);
container.Register(Classes.FromThisAssembly().BasedOn<IController>().LifestyleTransient());
container.Register(Component.For<IService>().ImplementedBy<CommonService>());
}
}
}
The Pipeline to Initialize:
namespace Web.Pipelines
{
public class InitializeWindsorControllerFactory
{
public void Process(PipelineArgs args)
{
IWindsorContainer container = new WindsorContainer().Install(FromAssembly.This());
IControllerFactory controllerFactory = new WindsorControllerFactory(container.Kernel);
SitecoreControllerFactory sitecoreControllerFactory = new SitecoreControllerFactory(controllerFactory);
System.Web.Mvc.ControllerBuilder.Current.SetControllerFactory(sitecoreControllerFactory);
}
}
}
And finally, the config to add to pipeline (I just incidentally used glass mapper's patch file to see if it would work)
My Controller is setup as such:
namespace Web.Areas.CastleTest.Controllers
{
public class TestController : Controller
{
ISitecoreContext _context;
ISitecoreService _master;
IService _service;
public ActionResult Index()
{
return View();
}
public TestController(IService srv, ISitecoreContext context, ISitecoreService service)
{
_service = srv;
_context = context;
_master = service;
}
public ActionResult CtrlTest()
{
var model = _context.GetItem<TestTemplate>(RenderingContext.CurrentOrNull.Rendering.DataSource);
return View(model);
}
}
}
The files are definitely getting patched, and the controller factory is definitely getting initialized. The error I am getting is:
[MissingMethodException: Constructor on type 'Web.Areas.CastleTest.Controllers.TestController' not found.]
System.RuntimeType.CreateInstanceImpl(BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes, StackCrawlMark& stackMark) +1481
System.Activator.CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes) +191
System.Activator.CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture) +27
Sitecore.Mvc.Helpers.TypeHelper.CreateObject(Type type, Object[] parameters) +44
Sitecore.Mvc.Controllers.SitecoreControllerFactory.CreateControllerInstance(RequestContext requestContext, String controllerName) +213
Sitecore.Mvc.Controllers.SitecoreControllerFactory.CreateController(RequestContext requestContext, String controllerName) +96
I have the feeling that Sitecore is not using WindsorControllerFactory to resolve the controllers. I know there are other ways to replace the default DI container in 8.2, but I need to use the pipeline for now, because I am really trying to debug this for another solution.