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:
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
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.
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 .
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();
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.
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.
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.
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.
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:
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...
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?
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.
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;
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.
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...
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)
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:
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
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:
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
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 .
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)
Unless you can point me in the right direction?
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:
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
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:
and this wouldn't touch other parts of Umbraco as far as I remember.
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.
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.
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.
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.
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();
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.
and
But when I run the application I still get the error
If I change it to just this (Cannot use HierarchicalLifetimeManager or it fails as above everytime)
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...
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:
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
.No idea why tho
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.
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.
I Love You
If you were a fluffy bear, I'd cuddle you all day!
You're a legend. Thanks.
LOL!
Your debt is to now update the umbraco IoC docs to include how to set it up using Unity ;)
Worked for my UnityConfig as well, thanks!
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
Hi there,
I have the same issue...did you find a solution?
Thanks in advance
Mark
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
please don't use this syntax:
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.
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
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
is working on a reply...