Copied to clipboard

Flag this post as spam?

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


  • Lee 1124 posts 3061 karma points
    Jun 20, 2014 @ 10:52
    Lee
    0

    Unable To Upgrade When Using Unity IOC - The type UmbracoContext does not have an accessible constructor

    I have an existing v7.1.3 project which has been running fine. I thought I would upgrade it to v7.1.4. I copied across the bin folder and the two umbraco folders. 

    When I browse to the site I get the following error (Full YSOD at bottom of post)

    The type UmbracoContext does not have an accessible constructor

    I am using Unity in the project for the IOC and it's running in an MVC way, we hijack the route and pass in our own models etc... Looking at the stack trace, Unity is kicking in on install and trying to resolve the UmbracoContext which is not setup in Unity (I haven't had an issue previously before the upgrade).

    So I thought I would try adding the following in my Unity bootstrapper:

    container.RegisterInstance(typeof(UmbracoContext), UmbracoContext.Current);

    Now this stops the YSOD, but when it asks me to login to continue the upgrade. I can't login. The page just refreshes and goes straight back to the login page with no errors or messages? 

    Hence I'm now stuck... Any advice / help appreciated.

    Full stack trace

    Server Error in '/' Application.
    The type UmbracoContext 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 UmbracoContext does not have an accessible constructor.
    Source Error: 
    An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.

    Stack Trace: 
    [InvalidOperationException: The type UmbracoContext does not have an accessible constructor.]
       Microsoft.Practices.ObjectBuilder2.DynamicMethodConstructorStrategy.ThrowForNullExistingObject(IBuilderContext context) +239
       lambda_method(Closure , IBuilderContext ) +60
       Microsoft.Practices.ObjectBuilder2.<>c__DisplayClass1.<GetBuildMethod>b__0(IBuilderContext context) +71
       Microsoft.Practices.ObjectBuilder2.DynamicMethodBuildPlan.BuildUp(IBuilderContext context) +42
       Microsoft.Practices.ObjectBuilder2.BuildPlanStrategy.PreBuildUp(IBuilderContext context) +333
       Microsoft.Practices.ObjectBuilder2.StrategyChain.ExecuteBuildUp(IBuilderContext context) +274
       Microsoft.Practices.ObjectBuilder2.BuilderContext.NewBuildUp(NamedTypeBuildKey newBuildKey) +250
       Microsoft.Practices.Unity.ObjectBuilder.NamedTypeDependencyResolverPolicy.Resolve(IBuilderContext context) +101
       lambda_method(Closure , IBuilderContext ) +209
       Microsoft.Practices.ObjectBuilder2.<>c__DisplayClass1.<GetBuildMethod>b__0(IBuilderContext context) +71
       Microsoft.Practices.ObjectBuilder2.DynamicMethodBuildPlan.BuildUp(IBuilderContext context) +42
       Microsoft.Practices.ObjectBuilder2.BuildPlanStrategy.PreBuildUp(IBuilderContext context) +333
       Microsoft.Practices.ObjectBuilder2.StrategyChain.ExecuteBuildUp(IBuilderContext context) +274
       Microsoft.Practices.Unity.UnityContainer.DoBuildUp(Type t, Object existing, String name, IEnumerable`1 resolverOverrides) +384
    
    [ResolutionFailedException: Resolution of the dependency failed, type = "Umbraco.Web.Install.Controllers.InstallController", name = "(none)".
    Exception occurred while: while resolving.
    Exception is: InvalidOperationException - The type UmbracoContext does not have an accessible constructor.
    -----------------------------------------------
    At the time of the exception, the container was:
    
      Resolving Umbraco.Web.Install.Controllers.InstallController,(none)
      Resolving parameter "umbracoContext" of constructor Umbraco.Web.Install.Controllers.InstallController(Umbraco.Web.UmbracoContext umbracoContext)
        Resolving Umbraco.Web.UmbracoContext,(none)
    ]
       Microsoft.Practices.Unity.UnityContainer.DoBuildUp(Type t, Object existing, String name, IEnumerable`1 resolverOverrides) +447
       Microsoft.Practices.Unity.UnityContainer.DoBuildUp(Type t, String name, IEnumerable`1 resolverOverrides) +50
       Microsoft.Practices.Unity.UnityContainer.Resolve(Type t, String name, ResolverOverride[] resolverOverrides) +48
       Microsoft.Practices.Unity.UnityContainerExtensions.Resolve(IUnityContainer container, Type t, ResolverOverride[] overrides) +61
       Unity.Mvc4.UnityDependencyResolver.GetService(Type serviceType) +189
       System.Web.Mvc.DefaultControllerActivator.Create(RequestContext requestContext, Type controllerType) +41
    
    [InvalidOperationException: An error occurred when trying to create a controller of type 'Umbraco.Web.Install.Controllers.InstallController'. Make sure that the controller has a parameterless public constructor.]
       System.Web.Mvc.DefaultControllerActivator.Create(RequestContext requestContext, Type controllerType) +179
       System.Web.Mvc.DefaultControllerFactory.GetControllerInstance(RequestContext requestContext, Type controllerType) +80
       System.Web.Mvc.DefaultControllerFactory.CreateController(RequestContext requestContext, String controllerName) +74
       Umbraco.Web.Mvc.MasterControllerFactory.CreateController(RequestContext requestContext, String controllerName) +196
       System.Web.Mvc.MvcHandler.ProcessRequestInit(HttpContextBase httpContext, IController& controller, IControllerFactory& factory) +197
       System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object state) +49
       System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContext httpContext, AsyncCallback callback, Object state) +50
       System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData) +16
       System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +301
       System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +155

     

  • Morten Christensen 596 posts 2773 karma points admin hq c-trib
    Jun 20, 2014 @ 11:02
    Morten Christensen
    0

    Hi,

    I have not used Unity before, as I usually go with Autofac, but it looks like Unity is trying to create a new instance of the UmbracoContext even though you register the instance. So maybe you need to specify that its used per request or somehow make it explicity that Unity should not try to create an instance of the UmbracoContext. Also, if Unity tries to inject stuff into the standard Umbraco controllers you probably want to specify which controllers or namespaces that Unity should or should not handle.

    Hope this helps get you in the right direction,

    Morten

  • Lee 1124 posts 3061 karma points
    Jun 20, 2014 @ 12:19
    Lee
    0

    Hey Morten,

    Thanks for the reply. I go with Unity as it seems so much easier to setup than other IOC's (Including Autofac).

    Everything is per request, but I don't see a way to stop it trying to create an instance of the UmbracoContext as I have registered Unity on AppStartUp and the InstallController has UmbracoContext passing into it's constructor... So it's just auto kicking in.

    It would be nice to use AutoFac as that's what Umbraco uses but with AutoFac don't you have to register all controllers one by one? I find Unity easier, as you don't need to register any controllers. Also, it handles classes which have other injected dependencies .

    container.BindInRequestScope<IDatabaseContext, DatabaseContext>();
    container.BindInRequestScope<IUnitOfWorkManager, UnitOfWorkManager>();
    container.BindInRequestScope<ICacheManager, MemoryCacheManager>();

     i.e. Above, the UnitOfWorkManager needs a DatabaseContext in it's constructor. Unity is smart enough to handle it. But when I register the UnitOfWorkManager using Autofac, it complains about the constructor needing the DatabaseContext for example (Also I don't fancy constantly adding every controller to AutoFac)

    builder.Register(c => new UnitOfWorkManager()).As<IUnitOfWorkManager>().InstancePerHttpRequest();

    Unless you can point me in the right direction?

  • Morten Christensen 596 posts 2773 karma points admin hq c-trib
    Jun 20, 2014 @ 13:14
    Morten Christensen
    0

    Umbraco doesn't use any kind of ioc container out of the box. Autofac is just my personal preference.

    You probably wouldn't want Unity to take over everything and try to do dependency injection in Umbraco. Some parts might work, but I would imagine you would have to do a lot of work wiring up the different parts to make all of Umbraco work with Unity. So the point I was trying to make was that you should probably specify which parts of the code you want Unity to handle. I haven't looked through the documentation for Unity, but I know that Autofac allows you to autoscan assemblies and have everything registered as 'Implemented interfaces'. For a more finegrained control you would either register everything explicitly without autoscan or autoscan and then ignore certain types or namespaces.

    For stuff like UmbracoContext, ApplicationContext, DatabaseContext and ServiceContext you should register the instance that you get from UmbracoContext.Current or ApplicationContext.Current and tell Unity to use that instance.

    I would have thought something like:

    container.RegisterInstance(typeof(UmbracoContext), UmbracoContext.Current);
    

    would Work, but seems like it doesn't if Unity is still trying to new it up.

    Shannon did write some documentation about Umbraco and IoC, but its fairly old and might be outdated: https://github.com/Shandem/Umbraco4Docs/blob/4.8.0/Documentation/Reference/Mvc/using-ioc.md

  • Morten Christensen 596 posts 2773 karma points admin hq c-trib
    Jun 20, 2014 @ 13:17
    Morten Christensen
    0

    How do you wire up autoscan in Unity? Does it just do it by default?

    In Autofac you specify the assembly to scan for registering your MVC controllers:

    container.RegisterControllers(typeof(MyApplication).Assembly);
    

    and this wouldn't touch other parts of Umbraco as far as I remember.

  • Lee 1124 posts 3061 karma points
    Jun 20, 2014 @ 21:15
    Lee
    0

    Yes I guess it does it by default? Below is my setup so far. Maybe it's too easy and shields from from stuff. But I've never had an issue with it.

    As I say, it runs absolutely fine (Front and backend). Injecting into RenderMvcController's and SurfaceController' etc... with no issues or with the backoffice. Only when I need to upgrade does this problem happen.

    public static class Bootstrapper
    {
        public static IUnityContainer Initialise()
        {
            var container = BuildUnityContainer();
    
            DependencyResolver.SetResolver(new UnityDependencyResolver(container));
    
            return container;
        }
    
        private static IUnityContainer BuildUnityContainer()
        {
            var container = new UnityContainer();
    
            // register all your components with the container here
            // it is NOT necessary to register your controllers
    
            // Database context, one per request, ensure it is disposed
            container.BindInRequestScope<IDatabaseContext, DatabaseContext>();
            container.BindInRequestScope<IUnitOfWorkManager, UnitOfWorkManager>();
            container.BindInRequestScope<ICacheManager, MemoryCacheManager>();
    
            container.BindInRequestScope<IPublishedContentService, PublishedContentService>();
            container.BindInRequestScope<INoteService, NoteService>();
            container.BindInRequestScope<IMemberService, MemberService>();
    
            // This is a little hack, or the umbraco installer YSOD's
            container.RegisterInstance(UmbracoContext.Current);
    
            return container;
        }
    
    }
    

    The UmbracoContext entry stops the YSOD, but it won't let me login/authorize the upgrade during the installer. I can login fine all other times. That's what's weird.

  • Morten Christensen 596 posts 2773 karma points admin hq c-trib
    Jun 20, 2014 @ 21:26
    Morten Christensen
    0

    Okay, well that is good news. I thought there would be more issues beyond the upgrade. It just seems weird that only the upgrade controllers would have an issue around the UmbracoContext. I would still assume that the wire up of the UmbracoContext is incorrect for Unity, as it should just work like the rest of Umbraco then. But maybe Shannon can shed some light on the upgrade/install process and what could be causing the issues.

  • Morten Christensen 596 posts 2773 karma points admin hq c-trib
    Jun 20, 2014 @ 21:30
    Morten Christensen
    0

    I would also assume that registering the instance with UmbracoContext.Current (from your initial post) would be sufficient. But since it throws an exception around newing up an UmbracoContext it sounds like the life cycle management is incorrect.

  • Shannon Deminick 1521 posts 5241 karma points
    Jun 22, 2014 @ 13:12
    Shannon Deminick
    0

    For any IoC container with Umbraco, you'll need to register a factory for UmbracoContext and ApplicationContext, not just the type since you cannot just new-up an instance of these as they need to be instantiated internally by Umbraco.

    Not sure how unity registers factories but it'd probably be something like:

    container.RegisterFactory(() => UmbracoContext.Current).InstancePerHttpRequest();

  • Lee 1124 posts 3061 karma points
    Jul 09, 2014 @ 10:24
    Lee
    0

    Just to revisit this. I cannot get it to work. It seems to register a factory, it still needs to have an interface. Which the UmbracoContext doesn't. I have read up and looked around and tried all the different variations suggested to get this to work, but to no avail.

            container.RegisterInstance(typeof(UmbracoContext), UmbracoContext.Current, new ContainerControlledLifetimeManager());
            container.RegisterInstance(typeof(ApplicationContext), ApplicationContext.Current, new ContainerControlledLifetimeManager());
    

    and

            container.RegisterInstance(UmbracoContext.Current, new HierarchicalLifetimeManager());
            container.RegisterInstance(ApplicationContext.Current, new HierarchicalLifetimeManager());
    

    But when I run the application I still get the error

    The type UmbracoContext does not have an accessible constructor.
    

    If I change it to just this (Cannot use HierarchicalLifetimeManager or it fails as above everytime)

            container.RegisterInstance(UmbracoContext.Current, new ContainerControlledLifetimeManager());
            container.RegisterInstance(ApplicationContext.Current, new ContainerControlledLifetimeManager());
    

    Then I don't get an error, but I cannot login to the Umbraco admin. ONLY when the installer is running. When the installer isn't triggered, I can login to the admin with this code present and have no issues with it.

    Just to check. Have you tested using AutoFac or another IOC with the installer/upgrader? As above. Unity works fine with no issues normally, it's ONLY when the installer/upgrader runs that I have a problem...

  • Shannon Deminick 1521 posts 5241 karma points
    Jul 09, 2014 @ 10:54
    Shannon Deminick
    101

    IoC shouldn't require an interface just a type. Surely Unity has a way to register a type as a factory. Apparently you need to use an InjectionFactory?

    http://bartwullems.blogspot.com.au/2011/03/unity-injectionfactory.html http://stackoverflow.com/questions/16835728/unity-singleton-code

    something like this maybe:

        container
                .RegisterType<UmbracoContext>(
                new ContainerControlledLifetimeManager(),
                new InjectionFactory(c => UmbracoContext.Current));
    
  • Simone Chiaretta 134 posts 541 karma points c-trib
    Feb 23, 2017 @ 15:41
    Simone Chiaretta
    1

    Registering it singleton doesn't work if using Unity with WebAPI as some authenticated web api won't work like that.

    To register it in a way it always work you should use the HierarchicalLifetimeManager.

            container.RegisterType<UmbracoContext>(
                new HierarchicalLifetimeManager(),
                new InjectionFactory(c => UmbracoContext.Current));
    

    No idea why tho

  • Shannon Deminick 1521 posts 5241 karma points
    Jul 09, 2014 @ 10:59
    Shannon Deminick
    0

    I'm also pretty sure you definitely don't want to use container.RegisterInstance because that will copy the current instance globally, you need to register a delegate. Since UmbracoContext is based on the CURRENT HttpContext, if you use container.RegisterInstance then you will end up with problems because it will be stale and you'll probably end up with the original/first UmbracoContext created being injected into everything which is not what you want at all.

  • Laurent Lequenne 121 posts 246 karma points
    Jan 19, 2017 @ 15:35
    Laurent Lequenne
    0

    This is the code of UmbracoContext.Current so the life time does not matter in this case as the value is always retrieved from the HttpContext if it exists and the static value if not.

        if (HttpContext.Current != null)
        {
            return (UmbracoContext)HttpContext.Current.Items["Umbraco.Web.UmbracoContext"];
        }
        return UmbracoContext._umbracoContext;
    
  • Lee 1124 posts 3061 karma points
    Jul 09, 2014 @ 11:20
    Lee
    0

    I Love You

    If you were a fluffy bear, I'd cuddle you all day!

    You're a legend. Thanks.

  • Shannon Deminick 1521 posts 5241 karma points
    Jul 10, 2014 @ 14:38
    Shannon Deminick
    1

    LOL!

    Your debt is to now update the umbraco IoC docs to include how to set it up using Unity ;)

  • nojaf 91 posts 300 karma points
    Jan 24, 2015 @ 14:49
    nojaf
    0

    Worked for my UnityConfig as well, thanks!

  • SM 2 posts 72 karma points
    Dec 11, 2015 @ 11:31
    SM
    0

    Hi Shannon/Lee,

    I just upgraded my solution from 7.2.4 to 7.3.4 and after upgrade while i'm trying to run the solution i'm getting The type UmbracoContext does not have an accessible constructor and unable to upgrade when using Unity IOC .Struggling around this for last 1 day .The old solution with 7.2.4 with Unity IOC perfectly works fine, just after upgrade it does not work. Would you please post the exact solution you had tried to resolve this, much appreciate your help.

    Thanks

  • Mark 11 posts 82 karma points
    May 18, 2016 @ 08:51
    Mark
    0

    Hi there,

    I have the same issue...did you find a solution?

    Thanks in advance

    Mark

  • Gunnar Már Óttarsson 4 posts 72 karma points
    Jul 18, 2017 @ 22:31
    Gunnar Már Óttarsson
    0

    I was unable to get either autofac or unity working with 7.6.

    Autofac kills the backoffice when registering mvc controllers but works fine for api controllers..

    Unity however is the opposite, works for mvc controllers but setting the dependency resolver for webapi gives a healthcontroller exception regularly in the backoffice...

    Issue up here

  • Shannon Deminick 1521 posts 5241 karma points
    Jul 24, 2017 @ 04:47
    Shannon Deminick
    0

    please don't use this syntax:

     builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
    

    And register things based on actual assembly references.

    See docs: https://our.umbraco.org/Documentation/Reference/using-ioc and make sure you are registering any assembly that contains MVC or WebApi controllers.

  • Gunnar Már Óttarsson 4 posts 72 karma points
    Jul 24, 2017 @ 10:28
    Gunnar Már Óttarsson
    0

    Thanks, after some more work i finally got everything working. Unity as well which was my ultimate goal anyway :)

    I don't know if it would be useful but i could try updating the docs with a unity example.

    This was my final configuration:

    https://pastebin.com/SNQruvsg

    https://pastebin.com/rvZvH3C4

    https://pastebin.com/mQLJqD13

  • Shannon Deminick 1521 posts 5241 karma points
    Jul 24, 2017 @ 10:33
    Shannon Deminick
    0

    we'd love any contributions to the docs if you have a few minutes to create Unity examples?

    docs page: https://our.umbraco.org/Documentation/Reference/using-ioc

    source code for this page: https://github.com/umbraco/UmbracoDocs/blob/master/Reference/using-ioc.md

Please Sign in or register to post replies

Write your reply to:

Draft