Upgrading - Error in ContentFactoryInitialization

Howdy!

This week I have been upgrading an older Episerver site from CMS 7.15 to latest and greatest. Before the actual upgrade work began (or even estimated/pitched to the client) we had dived into the internals of the application to make sure that we didn't have any big customizations or hacks potentially breaking the upgrade path.

The approach used was upgrading to the latest version in each major version, resolving breaking changes and addressing any usages of APIs marked as obsolete.
This worked very well and progress was steady - then we hit a snag...

Initialize action failed for Initialize on class EPiServer.Initialization.Internal.ContentFactoryInitialization, EPiServer, Version=11.6.0.0, Culture=neutral, PublicKeyToken=8fe83dea738b45b7
   at EPiServer.Framework.Initialization.InitializationEngine.InitializeModules()
   at EPiServer.Framework.Initialization.InitializationEngine.ExecuteTransition(Boolean continueTransitions)
   at EPiServer.Framework.Initialization.InitializationModule.EngineExecute(HostType hostType, Action`1 engineAction)
   at EPiServer.Framework.Initialization.InitializationModule.FrameworkInitialization(HostType hostType)
   at EPiServer.Global..ctor()
   at **REDACTED**.Global..ctor()
   at ASP.global_asax..ctor()
Activation error occurred while trying to get instance of type ContentFactory, key ""
   at EPiServer.ServiceLocation.ServiceLocatorImplBase.GetInstance(Type serviceType, String key)
   at EPiServer.ServiceLocation.ServiceLocatorImplBase.GetInstance[TService]()
   at EPiServer.Initialization.Internal.ContentFactoryInitialization.Initialize(InitializationEngine context)
   at EPiServer.Framework.Initialization.Internal.ModuleNode.Execute(Action a, String key)
   at EPiServer.Framework.Initialization.Internal.ModuleNode.Initialize(InitializationEngine context)
   at EPiServer.Framework.Initialization.InitializationEngine.InitializeModules()
Failure while building 'Lambda: Invoke(value(EPiServer.ServiceLocation.Internal.StructureMapConfiguredType`1+<>c__DisplayClass11_0`1[EPiServer.Core.IContentModelUsage,EPiServer.Core.IContentModelUsage]).instanceAccessor, value(EPiServer.ServiceLocation.Internal.StructureMapConfiguredType`1[EPiServer.Core.IContentModelUsage])._serviceLocator)', check the inner exception for details
1.) Lambda: Invoke(value(EPiServer.ServiceLocation.Internal.StructureMapConfiguredType`1+<>c__DisplayClass11_0`1[EPiServer.Core.IContentModelUsage,EPiServer.Core.IContentModelUsage]).instanceAccessor, value(EPiServer.ServiceLocation.Internal.StructureMapConfiguredType`1[EPiServer.Core.IContentModelUsage])._serviceLocator)
2.) Instance of EPiServer.Core.IContentModelUsage
3.) new ModelMerger(*Default of IContentModelUsage*, *Default of ContentModelOptions*)
4.) EPiServer.DataAbstraction.RuntimeModel.Internal.ModelMerger
5.) Instance of EPiServer.DataAbstraction.RuntimeModel.Internal.ModelMerger
6.) new DefaultPropertyDefinitionRepository(*Default of ContentTypeModelRepository*, *Default of ITabDefinitionRepository*, *Default of ServiceAccessor<PropertyDefinitionDB>*, *Default of ModelMerger*, *Default of ISynchronizedObjectInstanceCache*)
7.) EPiServer.DataAbstraction.Internal.DefaultPropertyDefinitionRepository
8.) Instance of EPiServer.DataAbstraction.IPropertyDefinitionRepository (EPiServer.DataAbstraction.Internal.DefaultPropertyDefinitionRepository)
9.) new ContentTypeDB(*Default of ServiceAccessor<IDatabaseExecutor>*, *Default of IPropertyDefinitionRepository*, *Default of IPropertySettingsRepository*, *Default of ContentTypeModelRepository*, *Default of DatabaseDateTimeHandler*, *Default of ISynchronizedObjectInstanceCache*, *Default of IPrincipalAccessor*)
10.) EPiServer.DataAccess.Internal.ContentTypeDB
11.) Instance of EPiServer.DataAccess.Internal.ContentTypeDB
12.) new DefaultContentTypeRepository(*Default of ContentTypeModelRepository*, *Default of ContentTypeDB*, *Default of ModelMerger*, *Default of ITabDefinitionRepository*, *Default of IPropertyDefinitionTypeRepository*, *Default of ITypeReferenceAnalyzer*, *Default of IPropertyDefinitionRepository*, *Default of ISynchronizedObjectInstanceCache*)
13.) EPiServer.DataAbstraction.Internal.DefaultContentTypeRepository
14.) Instance of EPiServer.DataAbstraction.IContentTypeRepository (EPiServer.DataAbstraction.Internal.DefaultContentTypeRepository)
15.) new ContentDataBuilder(*Default of IPropertyDataFactory*, *Default of IContentTypeRepository*, *Default of IContentDataFactory<BlockData>*, *Default of ILanguageBranchRepository*, *Default of IPageDataMetadataBuilder*, *Default of IContentLanguageAccessor*, *Default of IPrincipalAccessor*)
16.) EPiServer.Construction.Internal.ContentDataBuilder
17.) Instance of EPiServer.Construction.IContentDataBuilder (EPiServer.Construction.Internal.ContentDataBuilder)
18.) new SharedBlockFactory(*Default of IContentDataBuilder*, *Default of ConstructorParameterResolver*, *Default of ServiceAccessor<ContentDataInterceptor>*)
19.) EPiServer.Construction.Internal.SharedBlockFactory
20.) Instance of EPiServer.Construction.ISharedBlockFactory (EPiServer.Construction.Internal.SharedBlockFactory)
21.) new ContentFactory(*Default of ISharedBlockFactory*, *Default of IContentDataFactory<IContent>*, *Default of IContentDataFactory<PageData>*, *Default of IContentDataBuilder*, *Default of IPropertyDataFactory*)
22.) EPiServer.Construction.Internal.ContentFactory
23.) Instance of EPiServer.Construction.Internal.ContentFactory
24.) Container.GetInstance(EPiServer.Construction.Internal.ContentFactory)
   at lambda_method(Closure , IBuildSession , IContext )
   at StructureMap.Building.BuildPlan.Build(IBuildSession session, IContext context)
   at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
   at StructureMap.SessionCache.GetObject(Type pluginType, Instance instance, ILifecycle lifecycle)
   at StructureMap.SessionCache.GetDefault(Type pluginType, IPipelineGraph pipelineGraph)
   at StructureMap.Container.GetInstance(Type pluginType)
   at EPiServer.ServiceLocation.ServiceLocatorImplBase.GetInstance(Type serviceType, String key)
Exception has been thrown by the target of an invocation.
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
   at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at EPiServer.ServiceLocation.Internal.ReflectiveServiceConfigurationHelper.<>c__DisplayClass0_1.<TryRegisterServiceFactoryMember>b__3(IServiceLocator c)
   at EPiServer.ServiceLocation.Internal.StructureMapConfiguration.TypedFactory`1.<Create>b__2_0(IServiceLocator s)
   at lambda_method(Closure , IBuildSession , IContext )
Activation error occurred while trying to get instance of type DefaultContentModelUsageService, key ""
   at EPiServer.ServiceLocation.ServiceLocatorImplBase.GetInstance(Type serviceType, String key)
   at EPiServer.ServiceLocation.ServiceLocatorImplBase.GetInstance[TService]()
Failure while building 'Lambda: Invoke(value(EPiServer.ServiceLocation.Internal.StructureMapConfiguredType`1+<>c__DisplayClass11_0`1[EPiServer.Core.IContentProviderManager,EPiServer.Core.IContentProviderManager]).instanceAccessor, value(EPiServer.ServiceLocation.Internal.StructureMapConfiguredType`1[EPiServer.Core.IContentProviderManager])._serviceLocator)', check the inner exception for details
1.) Lambda: Invoke(value(EPiServer.ServiceLocation.Internal.StructureMapConfiguredType`1+<>c__DisplayClass11_0`1[EPiServer.Core.IContentProviderManager,EPiServer.Core.IContentProviderManager]).instanceAccessor, value(EPiServer.ServiceLocation.Internal.StructureMapConfiguredType`1[EPiServer.Core.IContentProviderManager])._serviceLocator)
2.) Instance of EPiServer.Core.IContentProviderManager
3.) new DefaultContentModelUsageService(*Default of IContentProviderManager*)
4.) EPiServer.Core.Internal.DefaultContentModelUsageService
5.) Instance of EPiServer.Core.Internal.DefaultContentModelUsageService
6.) Container.GetInstance(EPiServer.Core.Internal.DefaultContentModelUsageService)

Ah, this should be familiar to an Episerver developer. Somewhere StructureMap can't resolve its dependencies. Alright, we could fix this in a jiffy, surely? We have done this before. Well not this exact issue. Hmm....

I couldn't get my head around which configuration/module broke the initialization/DI. What had changed?
Adding to the confusion was that the log4net logging had broken down due to some unresolved third-party library preventing us from dragging in the latest EPiServer.Logging.Log4net nuget package.

Quite a few hours passed and a multitude of Google searches later and the penny finally dropped. During the upgrade the EPiServer.Framework namespace had split into multiple parts as clearly stated as breaking change in the docs.

This part was overlooked as the project had build time config transformations with a common base file for EPiServer.Framework which had not been synced to the updated one. The last segment of the assembly name EPiServer.Framework.AspNet for the type attribute was missing! These types were misdirected:

  • VirtualPathNonUnifiedProvider
  • FileXmlLocalizationProvider

Like so (other attributes omitted for brevity):

<virtualPathProviders>
  <add type="EPiServer.Web.Hosting.VirtualPathNonUnifiedProvider, EPiServer.Framework" />
  <!-- should be -->
  <add type="EPiServer.Web.Hosting.VirtualPathNonUnifiedProvider, EPiServer.Framework.AspNet" />
</virtualPathProviders>
<localization>
  <providers>
    <add type="EPiServer.Framework.Localization.XmlResources.FileXmlLocalizationProvider, EPiServer.Framework" />
    <!-- should be -->
    <add type="EPiServer.Framework.Localization.XmlResources.FileXmlLocalizationProvider, EPiServer.Framework.AspNet" />
  </providers>
</localization>

Finally, the issue was solved.

Hopefully anyone in the same spot can now solve the issue through Google as I leave this post for posterity.
Relevant xkcd: Wisdom of the Ancients

Cheers!