Hi I'm trying to get Microsoft's Unity IOC container to play nice with Umbraco. I can inject my dependencies into my UmbracoApiControllers fine by setting the WebApi's DependencyResolver, eg:
GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(UnityConfig.GetConfiguredContainer());
All is good - but when I log into the back office and go to the users section I get the following error:
Failed to retrieve data for child nodes undefined
The type XmlTreeNode does not have an accessible constructor.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.InvalidOperationException: The type XmlTreeNode does not have an accessible constructor.
Stack Trace:
at Microsoft.Practices.ObjectBuilder2.DynamicMethodConstructorStrategy.ThrowForNullExistingObject(IBuilderContext context)
at lambda_method(Closure , IBuilderContext )
at Microsoft.Practices.ObjectBuilder2.DynamicBuildPlanGenerationContext.<>c__DisplayClass1.<GetBuildMethod>b__0(IBuilderContext context)
at Microsoft.Practices.ObjectBuilder2.DynamicMethodBuildPlan.BuildUp(IBuilderContext context)
at Microsoft.Practices.ObjectBuilder2.BuildPlanStrategy.PreBuildUp(IBuilderContext context)
at Microsoft.Practices.ObjectBuilder2.StrategyChain.ExecuteBuildUp(IBuilderContext context)
at Microsoft.Practices.ObjectBuilder2.BuilderContext.NewBuildUp(NamedTypeBuildKey newBuildKey)
at Microsoft.Practices.Unity.ObjectBuilder.NamedTypeDependencyResolverPolicy.Resolve(IBuilderContext context)
at lambda_method(Closure , IBuilderContext )
at Microsoft.Practices.ObjectBuilder2.DynamicBuildPlanGenerationContext.<>c__DisplayClass1.<GetBuildMethod>b__0(IBuilderContext context)
at Microsoft.Practices.ObjectBuilder2.DynamicMethodBuildPlan.BuildUp(IBuilderContext context)
at Microsoft.Practices.ObjectBuilder2.BuildPlanStrategy.PreBuildUp(IBuilderContext context)
at Microsoft.Practices.ObjectBuilder2.StrategyChain.ExecuteBuildUp(IBuilderContext context)
at Microsoft.Practices.Unity.UnityContainer.DoBuildUp(Type t, Object existing, String name, IEnumerable`1 resolverOverrides)
This is because Unity is trying to inject into LegacyTreeController and obviously not being able to. This must be because LegacyTreeController Inherits from ApiController at the lowest level and Unity wants to be involved with all WebApi controllers.
If I do not set GlobalConfiguration.Configuration.DependencyResolver at start-up the back office works perfectly.
Is there a known work around for this? Since the MVC side of DI works find I assume I'm doing something wrong?
With a little help I've managed to come up with a fairly hackie work around for this.
I've created my own implementation of IHttpControllerActivator. WebApi has got its own default implementation of IHttpControllerActivator named DefaultHttpControllerActivator. The DefaultHttpControllerActivator class uses the set DependencyResolver to find the controllers dependencies. This causes issues with the Umbraco back office api controllers.
My class wraps the default Activator and calls it for everything apart from Umbraco's controllers. This is untested and unproven. I'm only putting it here to see if anyone has a better way of getting it working or if this is a viable workaround.
using System;
using System.Net.Http;
using System.Web.Http.Controllers;
using System.Web.Http.Dispatcher;
public class UmbracoWebApiHttpControllerActivator : IHttpControllerActivator
{
private readonly DefaultHttpControllerActivator _defaultHttpControllerActivator;
public UmbracoWebApiHttpControllerActivator()
{
this._defaultHttpControllerActivator = new DefaultHttpControllerActivator();
}
public IHttpController Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)
{
IHttpController instance =
this.IsUmbracoController(controllerType)
? Activator.CreateInstance(controllerType) as IHttpController
: this._defaultHttpControllerActivator.Create(request, controllerDescriptor, controllerType);
return instance;
}
private bool IsUmbracoController(Type controllerType)
{
return controllerType.Namespace != null
&& controllerType.Namespace.StartsWith("umbraco", StringComparison.InvariantCultureIgnoreCase);
}
}
I also had to register this class within my Unity Container to get it working:
var container = new UnityContainer();
// Work around to keep umbraco back office API controllers working.
container.RegisterType<IHttpControllerActivator, UmbracoWebApiHttpControllerActivator>();
Thanks Sebastiaan - their taking primarily about the MVC side. In Microsoft's wisdom they made WebApi and MVC work is slightly different ways. I've already got the MVC part working its just the WebApi part that's proving harder.
My fault for using Unity really. I wouldn't need my hack if I was using AutoFrac...
This UmbracoWebApiHttpControllerActivator-solution worked for me! Thanks for sharing it!
Another tip, I got an error from StructureMap saying that it could not create an instance of IDatabaseFactory, turns out I have missed to add the ApplicationContext-instance to the IOC.
Markus did you managed to run StructureMap with Umbraco 7 ?
After installing StructureMap from Nuget I'm getting this error "Activation error occurred while trying to get instance of type ContentItemBinder, key \"\"".
I have allready try UmbracoWebApiHttpControllerActivator but with no result.
For Unity, a slightly easier method than creating your own IHttpControllerActivator is to register the LegacyTreeController with Unity. Just add the following to your registration code:
7.1.4 WebApi and Unity IOC brakes BackOffice
Hi I'm trying to get Microsoft's Unity IOC container to play nice with Umbraco. I can inject my dependencies into my
UmbracoApiControllers
fine by setting the WebApi's DependencyResolver, eg:All is good - but when I log into the back office and go to the users section I get the following error:
This is because Unity is trying to inject into
LegacyTreeController
and obviously not being able to. This must be becauseLegacyTreeController
Inherits fromApiController
at the lowest level and Unity wants to be involved with all WebApi controllers.If I do not set
GlobalConfiguration.Configuration.DependencyResolver
at start-up the back office works perfectly.Is there a known work around for this? Since the MVC side of DI works find I assume I'm doing something wrong?
With a little help I've managed to come up with a fairly hackie work around for this.
I've created my own implementation of
IHttpControllerActivator
. WebApi has got its own default implementation ofIHttpControllerActivator
namedDefaultHttpControllerActivator
. TheDefaultHttpControllerActivator
class uses the setDependencyResolver
to find the controllers dependencies. This causes issues with the Umbraco back office api controllers.My class wraps the default Activator and calls it for everything apart from Umbraco's controllers. This is untested and unproven. I'm only putting it here to see if anyone has a better way of getting it working or if this is a viable workaround.
I also had to register this class within my Unity Container to get it working:
I have no clue about any of this, but I just wanted to point you to a thread that might offer some extra inspiration:
http://our.umbraco.org/forum/getting-started/installing-umbraco/53839-Unable-To-Upgrade-When-Using-Unity-IOC-The-type-UmbracoContext-does-not-have-an-accessible-constructor
Thanks Sebastiaan - their taking primarily about the MVC side. In Microsoft's wisdom they made WebApi and MVC work is slightly different ways. I've already got the MVC part working its just the WebApi part that's proving harder.
My fault for using Unity really. I wouldn't need my hack if I was using AutoFrac...
This UmbracoWebApiHttpControllerActivator-solution worked for me! Thanks for sharing it!
Another tip, I got an error from StructureMap saying that it could not create an instance of IDatabaseFactory, turns out I have missed to add the ApplicationContext-instance to the IOC.
My config looks like this now:
x.For<IHttpControllerActivator>().Use<UmbracoWebApiHttpControllerActivator>();
x.For<UmbracoContext>().Use(UmbracoContext.Current);
x.For<ApplicationContext>().Use(ApplicationContext.Current);
Markus did you managed to run StructureMap with Umbraco 7 ?
After installing StructureMap from Nuget I'm getting this error "Activation error occurred while trying to get instance of type ContentItemBinder, key \"\"".
I have allready try UmbracoWebApiHttpControllerActivator but with no result.
Also when I put:
For<UmbracoContext>().Use(UmbracoContext.Current);
For<ApplicationContext>().Use(ApplicationContext.Current);
into my config I got errors because UmbracoContext.Current and ApplicationContext.Current are nulls;
Could you please tell me how to configure StructureMap to work with Umbraco 7 ?
For Unity, a slightly easier method than creating your own IHttpControllerActivator is to register the LegacyTreeController with Unity. Just add the following to your registration code:
See here for explanation:
http://www.devtrends.co.uk/blog/using-unity.mvc5-and-unity.webapi-in-umbraco
(getting 500 errors posting. This is my 4th attempt. This time without link)
is working on a reply...