By enabling Windsor Container integration, your controllers and filters might request dependencies that can be satisfied by the container, thus leading your design to a loosely coupled architecture.
Table of contents
- Necessary assemblies on the web project
- Web.config
- Global.asax
- Container set up
- Benefits
- specific configuration for a controller
Necessary assemblies on the web project
Make your web project reference the following assemblies:
- Castle.DynamicProxy.dll
- Castle.Model.dll
- Castle.MicroKernel.dll
- Castle.Windsor.dll
- Castle.MonoRail.WindsorExtension.dll
Web.config
Use the useWindsorIntegration attribute:
<?xml version="1.0" encoding="utf-8" ?> <configuration> <configSections> <section name="monoRail" type="Castle.MonoRail.Engine.Configuration.MonoRailSectionHandler, Castle.MonoRail.Engine" /> <section name="castle" type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor" /> </configSections> <monoRail useWindsorIntegration="true"> <viewEngine viewPathRoot="views" customEngine="Castle.MonoRail.Framework.Views.NVelocity.NVelocityViewEngine, Castle.MonoRail.Framework.Views.NVelocity" /> </monoRail> <castle> <!-- component and facilities configuration goes here --> </castle> </configuration>
Global.asax
You must make your container available to the web application. The best place for it is the global.asax:
<%@ Application Inherits="YourApp.Web.HttpApplication" %>
namespace YourApp.Web {
using System;
using System.Web;
using Castle.Windsor;
using Castle.ActiveRecord;
public class HttpApplication : HttpApplication, IContainerAccessor
{
private static WebAppContainer container;
public void Application_OnStart()
{
container = new WebAppContainer();
}
public void Application_OnEnd()
{
container.Dispose();
}
public IWindsorContainer Container
{
get { return container; }
}
}
}
Container set up
You must register a facility named MonoRailFacility.
It ensures that the lifestyle of each controller is set to Transient - as using the default, singleton, would be a terrible mistake and register each component/controller on the ControllerTree.
|
Also note that from now on, your controllers (and optionally the filters) are standard components, and need to be registered on the container |
{
using System;
using YourApp.Web.Controllers;
using Castle.Model.Resource;
using Castle.Windsor.Configuration.Interpreters;
using Castle.MonoRail.WindsorExtension;
public class WebAppContainer : AppContainer
{
public WebAppContainer() : base( new XmlInterpreter( new ConfigResource() ) )
{
}
protected override void RegisterFacilities()
{
base.RegisterFacilities();
AddFacility( "rails", new MonoRailFacility() );
}
protected override void RegisterComponents()
{
base.RegisterComponents();
AddComponent( "home.controller", typeof(HomeController) );
}
}
}
Benefits
From this point your controllers and filters can use the container auto-wiring capabilities.
A specific configuration for a controller
Suppose you have a controller that receives files uploads. Where should it store the files? Make it configurable!
On the controller
public class ImageGalleryController : Controller { ... public ImageGalleryController(String imageDirectory) { this.imageDirectory = imageDirectory; } ... }
Let's assume that this controller was registered on the container with the key imagegallery.controller. On the configuration section:
<castle>
<components>
<component id="imagegallery.controller">
<parameters>
<imageDirectory>C:\mytempdir\safedir</imageDirectory>
</parameters>
</component>
<components>
</castle>
Your controller could assume a default directory and allow it to be overriden as well
public class ImageGalleryController : Controller { private String imageDirectory = Environment.GetFolderPath( Environment.SpecialFolder.ApplicationData ); public ImageGalleryController() { } public string ImageDirectory { get { return imageDirectory; } set { imageDirectory = value; } } ... }
The previous configuration for the component still valid. But now it's optional as the controller can live without it.

Instead of calling AddComponent for each controller, you could call:
protected void RegisterComponents(){ Register( AllTypes.Of<IController>().FromAssembly(Assembly.GetExecutingAssembly())); }