Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Pogo 6 posts 28 karma points
    Jul 29, 2014 @ 12:15
    Pogo
    0

    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:

    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?

  • Pogo 6 posts 28 karma points
    Jul 29, 2014 @ 12:50
    Pogo
    2

    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>();
    
  • Sebastiaan Janssen 4695 posts 13243 karma points MVP admin hq
    Jul 29, 2014 @ 15:22
    Sebastiaan Janssen
    0

    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

  • Pogo 6 posts 28 karma points
    Jul 29, 2014 @ 15:58
    Pogo
    0

    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...

  • Markus Johansson 1536 posts 4318 karma points
    Sep 20, 2014 @ 17:55
    Markus Johansson
    0

    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); 

  • Pawel Bres 39 posts 160 karma points c-trib
    Jan 20, 2015 @ 15:23
    Pawel Bres
    0

    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 ?

  • P@010 10 posts 52 karma points
    Mar 26, 2015 @ 17:26
    P@010
    0

    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:

    container.RegisterType<LegacyTreeController>(new InjectionConstructor());

    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)

Please Sign in or register to post replies

Write your reply to:

Draft