I use Castle Windsor with Umbraco using WebActivator to register the container. When using this method there is no difference between using Castle Windsor with Umbraco and a native MVC application.
/// <summary> /// Initializes a new instance of the <see cref="WindsorDependencyResolver"/> class. /// </summary> /// <param name="kernel">The Castle Windsor kernel.</param> public WindsorDependencyResolver(IKernel kernel) { this.kernel = kernel; }
#endregion
#region Public Methods
/// <summary> /// Resolves singly registered services that support arbitrary object creation. /// </summary> /// <param name="serviceType">The type of the requested service or object.</param> /// <returns>The requested service or object.</returns> public object GetService(Type serviceType) { return this.kernel.HasComponent(serviceType) ? this.kernel.Resolve(serviceType) : null; }
/// <summary> /// Resolves multiply registered services. /// </summary> /// <param name="serviceType">The type of the requested services.</param> /// <returns>The requested services.</returns> public IEnumerable<object> GetServices(Type serviceType) { return this.kernel.ResolveAll(serviceType) as IEnumerable<object>; }
Jeroen - I found this on the weekend but it didnt work.
Luke - Looks promising, I will give it a go and see how I get on. The problem I was having is it must of overwritten the default ControllerFactory and basically wasn't doing any DIing lol. Cue lots of swearing!
I use Castle Windsor with Umbraco using WebActivator to register the container. When using this method there is no difference between using Castle Windsor with Umbraco and a native MVC application.
/// <summary> /// Initializes a new instance of the <see cref="WindsorDependencyResolver"/> class. /// </summary> /// <param name="kernel">The Castle Windsor kernel.</param> public WindsorDependencyResolver(IKernel kernel) { this.kernel = kernel; }
#endregion
#region Public Methods
/// <summary> /// Resolves singly registered services that support arbitrary object creation. /// </summary> /// <param name="serviceType">The type of the requested service or object.</param> /// <returns>The requested service or object.</returns> public object GetService(Type serviceType) { return this.kernel.HasComponent(serviceType) ? this.kernel.Resolve(serviceType) : null; }
/// <summary> /// Resolves multiply registered services. /// </summary> /// <param name="serviceType">The type of the requested services.</param> /// <returns>The requested services.</returns> public IEnumerable<object> GetServices(Type serviceType) { return this.kernel.ResolveAll(serviceType) as IEnumerable<object>; }
I just done this with ninject its really really easy. So in your umbraco website nuget in ninject https://www.nuget.org/packages/Ninject.MVC3/3.0.0.6 that will add in your app_start folder class called NinjectWebCommon in there you have method
Thanks for replying so quick but apologies for my delayed response. I'm on 6.1.1 which would explain why, I'll upgrade now and see what happens. thanks
TL;DR If you use Castle Windsor with MVC3-4 Controllers, dont use IDependencyResolver but IControllerFactory If you use Castle Windsor with MVC4 Web Api Controllers, use IDependencyResolver and implement IDependencyScope
MVC:
Castle Windsor could have problems to Release() your dependencies if you use System.Web.Mvc.IDependencyResolver, because this interface lacks a Release() method and a Scope mechanism.
( AutoFac/Ninject use a HttpModule for tracking and releasing per-web-request dependencies [graphs]. )
System.Web.Mvc.IControllerFactory on the other hand, has a explicit Release() method.
Web API:
The Web API Dependency Resolver System.Web.Http.Dependencies.IDependencyResolver has a Scope mechanism to let Castle Windsor know when to release the dependency.
I have been using the ControllerFactory method with Castle Windsor for some time, but I've noticed the number of calls to CreateController and ReleaseController do not match up.
I think I have traced this to a bug in Umbraco. There is documented functionality in https://github.com/umbraco/Umbraco-CMS/blob/6.2.0/src/Umbraco.Web/Mvc/UmbracoMvcHandler.cs which means 2 controller instances are created for each request. One is created by Umbraco in StoreControllerInRouteDefinition and the other by MVC itself in the MvcHandler class as per standard MVC functionality. However I don't think the instance created in the StoreControllerInRouteDefinition method in UmbracoMvcHandler is ever passed to the controller factory for release.
Has anybody else using Castle Windsor or other customer ControllerFactory implementations seen this?
as long as the controllers are registered correctly within Windsor with a PerWebRequest Lifestyle ( and not Transient Lifestyle, witch would anyway be wrong ), the ControlleFactory.CreateController(...) would return same instance. So eventually there is only 1 instance to release.
Umbraco 6 and Dependancy Injection
All,
Just wondering, has anybody ever got DI/IoC working in Umbraco 6?
Been swearing at Umbraco all day trying to get Castle.Windsor and Autofac (seperatly not both at the same time!) working but no joy.
Thanks
Gareth
Hello,
I haven't used it with Umbraco yet, but these docs might help: http://our.umbraco.org/Documentation/Reference/Mvc/using-ioc
Jeroen
I use Castle Windsor with Umbraco using WebActivator to register the container. When using this method there is no difference between using Castle Windsor with Umbraco and a native MVC application.
<packages>
<package id="Castle.Core" version="3.2.0" targetFramework="net40" />
<package id="Castle.Windsor" version="3.2.0" targetFramework="net40" />
<package id="WebActivatorEx" version="2.0.1" targetFramework="net40" />
</packages> 
In AssemblyInfo.cs;
[assembly: WebActivatorEx.PreApplicationStartMethod(typeof((MyApp.StartupHandler), "PreApplicationStart")]
[assembly: WebActivatorEx.ApplicationShutdownMethodAttribute(typeof(MyApp.StartupHandler), "ApplicationShutdown")]
Startup Class
public class StartupHandler
{
private static IWindsorContainer container;
public static void PreApplicationStart()
{
SetupWindsorContainer();
DependencyResolver.SetResolver(new WindsorDependencyResolver(container));
DynamicModuleUtility.RegisterModule(typeof(PerWebRequestLifestyleModule));
}
public static void ApplicationShutdown()
{
DestroyWindsorContainer();
}
private static void SetupWindsorContainer()
{
string binDirectory = GetBinDirectoryPath();
AssemblyFilter filter = new AssemblyFilter(binDirectory, "MyApp*.dll"); container = new WindsorContainer();
container.AddFacility<TypedFactoryFacility>();
container.Kernel.Resolver.AddSubResolver(new ArrayResolver(container.Kernel, true));
container.Install(FromAssembly.InDirectory(filter));
} private static void DestroyWindsorContainer()
{
if (container != null)
{
container.Dispose();
container = null;
}
} private static string GetBinDirectoryPath()
{
bool isWebApplication = !string.IsNullOrEmpty(HttpRuntime.AppDomainId);
string binDirectory;
if (isWebApplication)
{
binDirectory = HttpRuntime.BinDirectory;
}
else
{
Assembly thisAssembly = Assembly.GetExecutingAssembly();
string assemblyLocation = thisAssembly.Location;
binDirectory = Path.GetDirectoryName(assemblyLocation);
}
return binDirectory;
}
}
Dependency Resolver Class;
/// <summary>
/// Castle windsor implementation of MVCs <see cref="System.Web.Mvc.IDependencyResolver"/> interface.
/// </summary>
public class WindsorDependencyResolver : System.Web.Mvc.IDependencyResolver
{
#region Fields and Constants
/// <summary>
/// The Castle Windsor kernel.
/// </summary>
private readonly IKernel kernel;
#endregion
#region Constructors
/// <summary>
/// Initializes a new instance of the <see cref="WindsorDependencyResolver"/> class.
/// </summary>
/// <param name="kernel">The Castle Windsor kernel.</param>
public WindsorDependencyResolver(IKernel kernel)
{
this.kernel = kernel;
}
#endregion
#region Public Methods
/// <summary>
/// Resolves singly registered services that support arbitrary object creation.
/// </summary>
/// <param name="serviceType">The type of the requested service or object.</param>
/// <returns>The requested service or object.</returns>
public object GetService(Type serviceType)
{
return this.kernel.HasComponent(serviceType) ? this.kernel.Resolve(serviceType) : null;
}
/// <summary>
/// Resolves multiply registered services.
/// </summary>
/// <param name="serviceType">The type of the requested services.</param>
/// <returns>The requested services.</returns>
public IEnumerable<object> GetServices(Type serviceType)
{
return this.kernel.ResolveAll(serviceType) as IEnumerable<object>;
}
#endregion
}
Thank you Jeroen and Luke.
Jeroen - I found this on the weekend but it didnt work.
Luke - Looks promising, I will give it a go and see how I get on. The problem I was having is it must of overwritten the default ControllerFactory and basically wasn't doing any DIing lol. Cue lots of swearing!
Thanks
Gareth
I use Castle Windsor with Umbraco using WebActivator to register the container. When using this method there is no difference between using Castle Windsor with Umbraco and a native MVC application.
<packages>
<package id="Castle.Core" version="3.2.0" targetFramework="net40" />
<package id="Castle.Windsor" version="3.2.0" targetFramework="net40" />
<package id="WebActivatorEx" version="2.0.1" targetFramework="net40" />
</packages> 
In AssemblyInfo.cs;
[assembly: WebActivatorEx.PreApplicationStartMethod(typeof((MyApp.StartupHandler), "PreApplicationStart")]
[assembly: WebActivatorEx.ApplicationShutdownMethodAttribute(typeof(MyApp.StartupHandler), "ApplicationShutdown")]
Startup Class
public class StartupHandler
{
private static IWindsorContainer container;
public static void PreApplicationStart()
{
SetupWindsorContainer();
DependencyResolver.SetResolver(new WindsorDependencyResolver(container));
DynamicModuleUtility.RegisterModule(typeof(PerWebRequestLifestyleModule));
}
public static void ApplicationShutdown()
{
DestroyWindsorContainer();
}
private static void SetupWindsorContainer()
{
string binDirectory = GetBinDirectoryPath();
AssemblyFilter filter = new AssemblyFilter(binDirectory, "MyApp*.dll"); container = new WindsorContainer();
container.AddFacility<TypedFactoryFacility>();
container.Kernel.Resolver.AddSubResolver(new ArrayResolver(container.Kernel, true));
container.Install(FromAssembly.InDirectory(filter));
} private static void DestroyWindsorContainer()
{
if (container != null)
{
container.Dispose();
container = null;
}
} private static string GetBinDirectoryPath()
{
bool isWebApplication = !string.IsNullOrEmpty(HttpRuntime.AppDomainId);
string binDirectory;
if (isWebApplication)
{
binDirectory = HttpRuntime.BinDirectory;
}
else
{
Assembly thisAssembly = Assembly.GetExecutingAssembly();
string assemblyLocation = thisAssembly.Location;
binDirectory = Path.GetDirectoryName(assemblyLocation);
}
return binDirectory;
}
}
Dependency Resolver Class;
/// <summary>
/// Castle windsor implementation of MVCs <see cref="System.Web.Mvc.IDependencyResolver"/> interface.
/// </summary>
public class WindsorDependencyResolver : System.Web.Mvc.IDependencyResolver
{
#region Fields and Constants
/// <summary>
/// The Castle Windsor kernel.
/// </summary>
private readonly IKernel kernel;
#endregion
#region Constructors
/// <summary>
/// Initializes a new instance of the <see cref="WindsorDependencyResolver"/> class.
/// </summary>
/// <param name="kernel">The Castle Windsor kernel.</param>
public WindsorDependencyResolver(IKernel kernel)
{
this.kernel = kernel;
}
#endregion
#region Public Methods
/// <summary>
/// Resolves singly registered services that support arbitrary object creation.
/// </summary>
/// <param name="serviceType">The type of the requested service or object.</param>
/// <returns>The requested service or object.</returns>
public object GetService(Type serviceType)
{
return this.kernel.HasComponent(serviceType) ? this.kernel.Resolve(serviceType) : null;
}
/// <summary>
/// Resolves multiply registered services.
/// </summary>
/// <param name="serviceType">The type of the requested services.</param>
/// <returns>The requested services.</returns>
public IEnumerable<object> GetServices(Type serviceType)
{
return this.kernel.ResolveAll(serviceType) as IEnumerable<object>;
}
#endregion
}
Guys,
I just done this with ninject its really really easy. So in your umbraco website nuget in ninject https://www.nuget.org/packages/Ninject.MVC3/3.0.0.6 that will add in your app_start folder class called NinjectWebCommon in there you have method
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<ISearchService>().To<SearchService>().InSingletonScope(); //this is my call gotcha make sure you have public constructor on the target
}
then in your surface controller
private readonly ISearchService _searchService;
/// <summary>
/// inject in this dependancy using ninject
/// </summary>
/// <param name="searchService"></param>
public SearchFormSurfaceController(ISearchService searchService)
{
_searchService = searchService;
}
and boh selectah you can haz ioc separation of concerns and all that other cool kid stuff ;-}
Ismail - worked like a charm dude. Thanks
Gareth
That looks really easy Ismail, Kudos.
Have blogged about it as well http://ismailmayat.wordpress.com/2013/07/25/umbraco-6-mvc-and-dependency-injection/ I still cannot get over how easy it is lol
I use Castle Windows and integrate it by subclassing UmbracoApplication and registering a WindsorControllerFactory
Martin, any code you can share?
Thanks
Gareth
you need at least version >= 6.1.2 https://github.com/umbraco/Umbraco-CMS/commit/aecc3d28bf2723877ce3f5a2b7db12eb20f799a3
Hi, Martin,
I just tried your approach in the example provided but I get an error on this line below, the error is
Cannot access internal class 'FilteredControllerFactoriesResolver' here.
Do you have a solution for this?
Thanks, Paul
Hi Paul,
on what version do you work?
Only version >= 6.1.2 have a public accessible. FilteredControllerFactoriesResolver. See https://github.com/umbraco/Umbraco-CMS/blob/release-6.1.2/src/Umbraco.Web/Mvc/FilteredControllerFactoriesResolver.cs
Hi Martin,
Thanks for replying so quick but apologies for my delayed response. I'm on 6.1.1 which would explain why, I'll upgrade now and see what happens. thanks
http://shazwazza.com/post/Using-IoC-with-Umbraco-MVC
TL;DR
If you use Castle Windsor with MVC3-4 Controllers, dont use IDependencyResolver but IControllerFactory
If you use Castle Windsor with MVC4 Web Api Controllers, use IDependencyResolver and implement IDependencyScope
MVC:
Castle Windsor could have problems to Release() your dependencies if you use System.Web.Mvc.IDependencyResolver, because this interface lacks a Release() method and a Scope mechanism.
( AutoFac/Ninject use a HttpModule for tracking and releasing per-web-request dependencies [graphs]. )
System.Web.Mvc.IControllerFactory on the other hand, has a explicit Release() method.
Web API:
The Web API Dependency Resolver System.Web.Http.Dependencies.IDependencyResolver has a Scope mechanism to let Castle Windsor know when to release the dependency.
http://mikehadlow.blogspot.it/2011/02/mvc-30-idependencyresolver-interface-is.html
http://stackoverflow.com/questions/4140860/castle-windsor-dependency-resolver-for-mvc-3
http://nikosbaxevanis.com/blog/2012/06/04/using-the-web-api-dependency-resolver-with-castle-windsor-part-2/
I have been using the ControllerFactory method with Castle Windsor for some time, but I've noticed the number of calls to CreateController and ReleaseController do not match up.
I think I have traced this to a bug in Umbraco. There is documented functionality in https://github.com/umbraco/Umbraco-CMS/blob/6.2.0/src/Umbraco.Web/Mvc/UmbracoMvcHandler.cs which means 2 controller instances are created for each request. One is created by Umbraco in StoreControllerInRouteDefinition and the other by MVC itself in the MvcHandler class as per standard MVC functionality. However I don't think the instance created in the StoreControllerInRouteDefinition method in UmbracoMvcHandler is ever passed to the controller factory for release.
Has anybody else using Castle Windsor or other customer ControllerFactory implementations seen this?
Hi Luke,
as long as the controllers are registered correctly within Windsor with a PerWebRequest Lifestyle ( and not Transient Lifestyle, witch would anyway be wrong ), the ControlleFactory.CreateController(...) would return same instance. So eventually there is only 1 instance to release.
The following test code ...
... would log:
is working on a reply...