Target .NET framework

Target .NET framework

As you can imagine a solution that has been around since Sitecore 7 has 'A LOT' of projects. My first plan was to visit each one and edit the target framework via the properties window, but after the first three projects of about 70, I thought to myself "This is quite laborious, you know what, this task is a prime candidate for automation". A quick search around uncovered a visual studio extension called TargetFrameworkMigrator. This extension made thing super quick, and I was done upgrading the .NET version to 4.6.2 in no time. One thing to note though that it did not like TDS projects, but unloading these projects resulted in an error-free experience :).

In this step I only focused on fixing build issues that related to the .NET version bump, trying not to think about Sitecore References.

Unable to change Project Target Framework

While working through the projects in the solution, I came across a project where the target framework was not updated automatically, manually updating the target resulted in no success.

Issue:

The referenced project 'xxx' is targeting a higher framework version (4.6.2) than this project’s current target framework version (4.5). This may lead to build failures if types from assemblies outside this project’s target framework are used by any project in the dependency chain.

Solution:

I cracked open the csproj file and found a customisation that started WcfTestClient.exe, this task was targeting .NET 4.5.

<StartArguments>/client:"WcfTestClient.exe"</StartArguments>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>

Updating the TargetFrameworkVersion on this to 4.6.2, I was then able to update the project target.

<TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>

I am unsure of the ramifications of this change.

Build output

I was not getting much information regarding the build errors I was encountering, so decided to increase the build output verbosity to detailed. Note this can increase the time it takes to build, so it's worth disabling once you have solved your issue.

Tools -> Options -> Projects and Solutions -> Build and Run

It was now clearer what the problems where.

Clean that build

At first, the solution did not build, and this slightly confused me, I expected no issues building. .Net 4.6.2 is an in-place update of 4.5 so things should continue to work. Before looking into the errors MSBuild was spitting out, I turned to my old friend clean solution, and BAM the errors were gone :)

After successfully building and deploying the code, a simple smoke test resulted in an operational site.

Step Two: Sitecore References

public void StepPreInit()
{
    Add Sitecore Nuget feed to Solution
}

Here is where I expected the fun to start, as there are many changes between 7 and 9, most of them breaking. My method was to work project to project, remove the Sitecore references replacing them with the corresponding .NoReference NuGet package, one reference at a time.

There were many issues I ran into when updating the Sitecore references, so I have split them into multiple entries.

log4net not found

Issue:

The type or namespace name 'log4net' could not be found (are you missing a using directive or an assembly reference?)

Solution:

Install the Sitecore.Logging.NoReferences NuGet package.

IsPageEditorEditing and IsPageEditor not found

The name of the page editor has changed, it’s all about the Experience now ;)

Issue:

'Context.PageMode' does not contain a definition for 'IsPageEditorEditing'
'Context.PageMode' does not contain a definition for 'IsPageEditor'

Solution:

IsPageEditorEditing becomes IsExperienceEditorEditing
IsPageEditor becomes IsExperienceEditor

IsPageEditorEditing and not found

The Link manager no longer exposes the Provider property.

Issue:

'LinkManager' does not contain a definition for 'Provider'

Solution:

You can use the ServiceLocator to help here, even though I consider, in general, them an anti-pattern, Sitecore is using one under the hood. You should consider constructor injection as this does not make class dependencies obscure.

Clone and not found

In version 7 Sitecore.ContentSearch had an extension method to clone objects, but it no longer does.

Issue:

'xxx' does not contain a definition for 'Clone' and no extension method 'Clone' accepting a first argument of type 'xxx' could be found (are you missing a using directive or an assembly reference?)	

Solution:

It’s probably best to understand why you needed the clone in the first place, and if you definitely need it then create your own extension method, better still make the class you are trying to clone implement ICloneable, then build the cloning logic with this particular class in mind.

No overload for method Render

In my version of WFFM the Sitecore.Forms.Core.dll had only two overloads in the latest version there are four.

Issue:

No overload for method 'Render' takes 3 arguments

Solution:

Update your code to use one of the new overloads

HtmlAgilityPack version conflicts

Issue:

Found conflicts between different versions of "HtmlAgilityPack" that could not be resolved.

Solution:

Install the HtmlAgilityPack NuGet package, in my case it was 1.4.9.5, check your version in Sitecore/bin.

Sitecore support binaries

There were many Sitecore support binaries. I decided that removing them was the best course of action as the issues they provided fixes for should have been addressed by the product team by now, it is vital however to understand what they were for so you can test these cases. One last note here, don't forget the configuration changes that patched them into the site.

Where is ITypeRegistrationsProvider

This error is a bit misleading, what the hell does the Microsoft.Practices.EnterpriseLibrary.Common doing causing an issue with OWIN?

Issue

Could not load type 'Microsoft.Practices.EnterpriseLibrary.Common.Configuration.ContainerModel.ITypeRegistrationsProvider' from assembly 'Microsoft.Practices.EnterpriseLibrary.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'.
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.TypeLoadException: Could not load type 'Microsoft.Practices.EnterpriseLibrary.Common.Configuration.ContainerModel.ITypeRegistrationsProvider' from assembly 'Microsoft.Practices.EnterpriseLibrary.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'.

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: 

[TypeLoadException: Could not load type 'Microsoft.Practices.EnterpriseLibrary.Common.Configuration.ContainerModel.ITypeRegistrationsProvider' from assembly 'Microsoft.Practices.EnterpriseLibrary.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'.]
   System.Reflection.CustomAttribute._CreateCaObject(RuntimeModule pModule, IRuntimeMethodInfo pCtor, Byte** ppBlob, Byte* pEndBlob, Int32* pcNamedArgs) +0
   System.Reflection.CustomAttribute.CreateCaObject(RuntimeModule module, IRuntimeMethodInfo ctor, IntPtr& blob, IntPtr blobEnd, Int32& namedArgs) +48
   System.Reflection.CustomAttribute.GetCustomAttributes(RuntimeModule decoratedModule, Int32 decoratedMetadataToken, Int32 pcaCount, RuntimeType attributeFilterType, Boolean mustBeInheritable, IList derivedAttributes, Boolean isDecoratedTargetSecurityTransparent) +787
   System.Reflection.CustomAttribute.GetCustomAttributes(RuntimeAssembly assembly, RuntimeType caType) +144
   Owin.Loader.DefaultLoader.SearchForStartupAttribute(String friendlyName, IList`1 errors, Boolean& conflict) +190
   Owin.Loader.DefaultLoader.GetDefaultConfiguration(String friendlyName, IList`1 errors) +68
   Owin.Loader.DefaultLoader.LoadImplementation(String startupName, IList`1 errorDetails) +89
   Owin.Loader.DefaultLoader.Load(String startupName, IList`1 errorDetails) +30
   Microsoft.Owin.Host.SystemWeb.OwinBuilder.GetAppStartup() +165
   Microsoft.Owin.Host.SystemWeb.OwinHttpModule.InitializeBlueprint() +37
   System.Threading.LazyInitializer.EnsureInitializedCore(T& target, Boolean& initialized, Object& syncLock, Func`1 valueFactory) +135
   Microsoft.Owin.Host.SystemWeb.OwinHttpModule.Init(HttpApplication context) +160
   System.Web.HttpApplication.RegisterEventSubscriptionsWithIIS(IntPtr appContext, HttpContext context, MethodInfo[] handlers) +580
   System.Web.HttpApplication.InitSpecial(HttpApplicationState state, MethodInfo[] handlers, IntPtr appContext, HttpContext context) +165
   System.Web.HttpApplicationFactory.GetSpecialApplicationInstance(IntPtr appContext, HttpContext context) +353
   System.Web.Hosting.PipelineRuntime.InitializeApplication(IntPtr appContext) +341

[HttpException (0x80004005): Could not load type 'Microsoft.Practices.EnterpriseLibrary.Common.Configuration.ContainerModel.ITypeRegistrationsProvider' from assembly 'Microsoft.Practices.EnterpriseLibrary.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'.]
   System.Web.HttpRuntime.FirstRequestInit(HttpContext context) +523
   System.Web.HttpRuntime.EnsureFirstRequestInit(HttpContext context) +107
   System.Web.HttpRuntime.ProcessRequestNotificationPrivate(IIS7WorkerRequest wr, HttpContext context) +688

Solution

The a setting was missing, and because Owin, for some reason, things the ITypeRegistrationsProvide is its start up class it tries to create an instance of it. The above mention setting fixed this problem. This Stack Overflow post goes into the deatils. This setting is present in the default Sitecore configuration. However, I must have dropped it by accident when merging the projects Web.confg with the Sitecore 9 Web.confg.

<add key="owin:appStartup" value="Sitecore.Owin.Startup, Sitecore.Owin"/>