How to Upgrade Umbraco Version 7 to Version 8

How to Upgrade Umbraco Version 7 to Version 8

Do you need an in depth, step-by-step walkthrough of how to deal with Umbraco version upgrades from version 7 to version 8?  Then this is the post for you!

Over the last year, we have upgraded several of our clients from Umbraco version 7 to Umbraco version 8. With each upgrade we find small surprises that we get to work through.  This post shares what we have learned so far.

Disclaimer: this post won't go into detail on a lot of the code changes that need to be made. We won't try to list or describe how to write custom Examine indexes in Umbraco 8 or how to convert an ApplicationStarting event handler in Umbraco 7 to Umbraco 8 Composers and Compositions. Instead, this is more of a roadmap to an Umbraco 8 upgrade that focuses on solving problems upgrading the database without losing data.

Umbraco 8 upgrades are complex and every Umbraco site is different. You will almost certainly have to add your own steps throughout the process and will run into unique challenges, but we think the following steps will get you close.

Things to know before you get started

What is a Migration?

In Umbraco 7.3.9, Umbraco introduced the concept of Migrations. A Migration in Umbraco is a one-off process that is run automatically when the site starts up. Umbraco uses Migrations to apply database changes during Umbraco upgrades. The executions of these migrations are tracked in the database, so Umbraco is able to tell which migrations have already been run.

Developers can write their own, custom Umbraco Migrations to automate any one-off process. ProWorks uses migrations to help migrate from one datatype to another without data loss. We created an Umbraco 7 package called Our.Umbraco.Migration to help developers bootstrap their own migrations into an Umbraco site. It comes with built in migration base classes which convert Content, Media, and Member pickers from id pickers to udi pickers. We also wrote a Skrift article about using Migrations: Skrift: Umbraco Migrations Made Easy

 

Important Umbraco Version Thresholds

These are important Umbraco version "thresholds" to be mindful of when upgrading Umbraco sites. Some of these are breaking changes that have bit us in the past. Others are just versions where important features are released.

  • When upgrading past Umbraco 7.3.0

    Make sure any and all public access settings at "/App_Data/access.config" are present on disk at the time of the upgrade. The public access settings are migrated to the database at this time and if the settings are not present at /App_Data/access.config, you will miss your chance to have all of the public access settings migrated automatically.

    This is where the "umbracoMigrations" table is introduced. From this point forward, Umbraco is better able to handle the database components of Umbraco upgrades. Once an Umbraco site reaches this point, developers can begin to write custom migrations of their own.

  • When upgrading past Umbraco 7.6.0

    Umbraco added Udis to the database in Umbraco 7.6.0. The primary way to uniquely identify Umbraco nodes changed from the node id to the Udi. New versions of the Content, Media, and Member Picker property editors were created to pick these nodes by Udi instead of node id. At this point, migrations can be written to convert any and id pickers to Udi pickers. The migrations do not need to be added immediately, but this is the earliest that they can be added.

  • When upgrading past Umbraco 7.7.0

    Umbraco changed the member role system from being user based to role/group based. The user specific permissions that the content editors are familiar with will be converted to role based permissions. You will notice new "migrated section access" groups. One of these new groups is created for each combination of specific user permissions. This is an important change to inform content editors of.

    Umbraco.NestedContent was added to the Umbraco core. At this point, migrations can be written to convert any and all Our.Umbraco.NestedContent data to the new, core Umbraco.NestedContent. The migrations do not need to be added immediately, but this is the earliest that they can be added.

  • When upgrading past Umbraco 7.14.0

    The Umbraco.MultiUrlPicker was added to the Umbraco core. At this point, migrations can be written to convert any and all RJP.MultiUrlPicker data to the new, core Umbraco.MultiUrlPicker. The migrations do not need to be added immediately, but this is the earliest that they can be added.

  • When upgrading past Umbraco 7.15.0

    Umbraco released the following fix: issues/3869. The purpose is to handle cases where content editors upload new images to existing media items that are picked in rich text editors. In these cases, the data in the rich text editors would still point to the old media file. This new feature updates the media path at render time using the "data-udi" property on the <img> tag. This is a great feature. However, we have found that some content editors who are more familiar with html will sometimes edit the img src manually. If content editors are in the habit of doing this, when the site is upgraded past Umbraco 7.15.0, the images edited this way could display the wrong file.

  • When upgrading past Umbraco 8.0.0

    There is a bug during the Umbraco 8 upgrade that will cause published nodes to become unpublished when those nodes have versions in the database that are saved but not published. A migration must be added to tweek the database and fix each of these unpublished nodes.

Overview of Upgrade Process

This is the birds eye view to all of the steps that go into an Umbraco 7 to Umbraco 8 upgrade. To help conceptualize an Umbraco upgrade, I find it helps to separate the upgrade of the database from the upgrade of the files in my mind. I'll list the upgrade steps for each separately below.

Upgrade the Umbraco database

Umbraco is getting better and better about supporting upgrades, but some of the earlier v7 upgrades are a still little more rough. When Upgrading to latest v7 and v8, there are some intermediate upgrades that must be completed first. You have to take a pit stop at each of these on your way to the latest and greatest. Below is a list of the intermediate upgrades and a short description of why we need to stop at each of these.

For each of the "Upgrade Umbraco database" steps below, you can point a vanilla Umbraco site of the new version at the existing Umbraco database and run through the upgrade wizard. This allows you to focus on the database upgrade without spending time moving and merging config files. Step #4 where the custom migrations run is the most complex part of the database upgrade.

  1. Upgrade the Umbraco database to 7.3.9
    Umbraco introduces Migrations
  2. Upgrade the Umbraco database to 7.6.14
    Umbraco introduces UDIs. Stop here to prevent errors during the upgrade.
  3. Upgrade the Umbraco database to 7.15.x (latest v7)
  4. Run custom v7 Migrations to convert datatypes
    • Node Id Pickers to Udi Pickers
    • RJP.MultiUrlPicker (or other link picker) to Umbraco.MultiUrlPicker
    • Our.Umbraco.NestedContent to Umbraco.NestedContent
    • Our.Umbraco.StackedContent to Umbraco.BlockList
    • Other datatypes that might need migration
  5. Upgrade the Umbraco database to 8.4.2
    Stop here to prevent database issues during the upgrade
  6. Upgrade the Umbraco database to the latest v8
  7. Run custom v8 Migrations
    • Fix published versions that became unpublished during upgrade to v8
    • Fix Umbraco.NestedContent JSON by adding {"key": "<Guid>"}
    • Fix miscellaneous grid and prevalue errors on upgrade

Upgrade the files

This upgrade of the files can usually happen after the Umbraco database upgrade to v8 complete.

  • Fix any custom code, so the site compiles. This includes an upgrade of the project to .NET Framework 4.7.2
  • Fix the templates
  • Deal with packages and extensions. Update/replace packages with v8 equivalents or remove them

Step By Step

Here it is. This is probably what everyone really wants to see. This is a step by step process to upgrading an Umbraco 7 site to an Umbraco 8 site.

Step 1: Upgrade the Umbraco database to 7.3.9

  • Download a vanilla Umbraco 7.3.9 site
  • Ensure that any public access data in your "/App_Data/access.config" is in place on the vanilla 7.3.9 site
  • Point the vanilla 7.3.9 site at the Umbraco database you want to upgrade
  • Run through the upgrade wizard

Step 2: Upgrade the Umbraco database to 7.6.14

Step 3: Upgrade the Umbraco database to 7.15.6 (or latest)

Step 4: Run v7 migrations to convert node id pickers to Udi pickers

Prior to Umbraco 7.6.0, the node pickers (Content Picker, Media Picker, Member Picker, Related Links, and Multinode Treepicker) all picked nodes by node id. New versions of these pickers that picked by udi have been introduced and before upgrading to Umbraco 8, all of the datatypes should be migrated to the new property editors and the data in the database should be converted to avoid data loss. ProWorks has written migrations to handle the following datatype conversions already:

  • Umbraco.RelatedLinks to Umbraco.RelatedLinks2
  • Umbraco.MultiNodeTreePicker to Umbraco.MultiNodeTreePicker2
  • Umbraco.MultipleMediaPicker to Umbraco.MediaPicker2
  • Umbraco.ContentPicker to Umbraco.ContentPicker2
  • Umbraco.MediaPicker to Umbraco.MediaPicker2
  • Umbraco.MemberPicker to Umbraco.MemberPicker2

We perform all of the above datatype migrations using the Our.Umbraco.Migrations package we created. To perform the above migrations using the Our.Umbraco.Migrations package follow these steps:

  1. Install the Our.Umbraco.Migrations package via nuget
  2. Add the following to the web.config
    <configuration>
      <migrationResolvers>
        <add name="ProductMigrations" type="Our.Umbraco.Migration.ProductMigrationResolver, Our.Umbraco.Migration">
        <add key="MonitoredProductNames" value="MyTestSite.Custom" />
        </add>
      </migrationResolvers>
    </configuration>
  3. Add the following class to the solution
    [Migration("1.0.0", 1, "MyTestSite.Custom")]
    public class V1_IdtoUdiMigration : IdToUdiMigration
    {
        // Calling the default base constructor this way will
        // trigger a full conversion of all id pickers to udi
        // pickers and all of the picked ids to udis.
        public V1_IdtoUdiMigration(ISqlSyntaxProvider sqlSyntax, ILogger logger) : base(sqlSyntax, logger)
        {
        }
    }
  4. Make sure that the "MonitoredProductNames" in the migrationResolvers configuration of the web.config matches the name on the [Migration] attribute on your migration class

Step 5: Run v7 migration to convert link pickers to the Umbraco.MultiUrlPicker

In all of our Umbraco 7 sites, we installed and made use of the RJP.MultiUrlPicker package for our link pickers. In Umbraco 7.14.0, Umbraco pulled it into the core. If your site uses the RJP.MultiUrlPicker property editor, it will need to be converted to the Umbraco.MultiUrlPicker before you upgrade to Umbraco 8. There is no migration required. The values picked in the database are similar enough. You just need to locate the datatypes and select the new Umbraco.MultiUrlPicker property editor.

If your site makes use of a different 3rd party link picker. You should check to see if that link picker is supported in Umbraco 8. If not, consider writing a migration to convert the datatypes and data to the Umbraco.MultiUrlPicker.

Step 6: Convert Our.Umbraco.NestedContent to Umbraco.NestedContent

In Umbraco 7.7.0, Umbraco pulled the 3rd party Our.Umbraco.NestedContent property editor into the core. If your site uses the Our.Umbraco.NestedContent property editor, it will need to be converted to the Umbraco.NestedContent property editor before you upgrade to Umbraco 8. There is no migration required. The values picked in the database are similar enough. You just need to locate the datatypes and select the new Umbraco.NestedContent property editor.

If your site makes use of any other similar packages like Our.Umbraco.StackedContent, consider writing a migration to convert the datatypes and data to the Umbraco.NestedContent. In Umbraco 8, a new property editor called the Block List Editor was created. You could also wait until Umbraco 8 and attempt to migrate your data to the Block List Editor.

Step 7: Upgrade the Umbraco database to 8.4.2

Step 8: Upgrade the Umbraco database to the latest version of Umbraco 8

Step 9: Nuget install Umbraco 8.x.x (latest) into your project

See the following nuget packages:

Step 10: Upgrade the projects to .NET Framework 4.7.2

Step 11: Convert Umbraco 7 code to Umbraco 8 so that the site compiles

In Umbraco 7, when you log errors you might make a call that looks like the following with the exception as the final argument of the method.

Logger.Error("Oops", ex);

In Umbraco 8, when you log an error, the exception is the first argument. If you don't fix this, it won't throw any exceptions. It will just ruin your logs.

Logger.Error(ex, "Oops");

Step 12: Convert Umbraco 7 Views, Partial Views, and Macros to Umbraco 8

I won't go into detail here. See the Umbraco 8 documentation on rendering content.

I found a small breaking change with the ".Siblings()" method that I hadn't seen documented elsewhere, so I'm describing that here. In Umbraco 7, calling ".Siblings()" would retrieve a list of sibling nodes including self. In Umbraco 8, if you want the same effect, call ".SiblingsAndSelf()".

Step 13: Deal with packages and extensions. Update/replace packages with v8 equivalents or remove them

Step 14: Run v8 migration to fix Umbraco.NestedContent JSON

The JSON in the Umbraco 8 versions of Umbraco.NestedContent requires a "key" property like {"key": }. The Umbraco 7 versions of NestedContent do not include this property. Consider writing a migration to add it where necessary.

Step 15: Run v8 migration to fix published/unpublished status of nodes

There is a bug during the Umbraco 8 upgrade that affects published nodes that have changes which have been saved but not published. Even if the node was published in Umbraco 7, if the node has any saved versions that aren't published yet, the node will be marked as unpublished when you upgrade. Consider writing a v8 migration must be added to tweek the database and fix each of these unpublished nodes. The below migration should do the trick

internal class UpdatePublishedVersionToLatest : MigrationBase
{
private const string UpdateSql = "UPDATE d SET d.published = 1, d.edited = 1 " +
    "FROM umbracoDocument d JOIN umbracoContentVersion cv ON cv.nodeId = d.nodeId JOIN umbracoDocumentVersion dv ON cv.id = dv.id " +
    "WHERE dv.published = 1 AND d.published = 0 AND d.edited = 0 AND d.nodeId IN (SELECT vc.nodeId FROM umbracoContentVersion vc JOIN umbracoDocumentVersion vd ON vc.id = vd.id WHERE vc.[current] = 1 AND vd.published = 0)";

public UpdatePublishedVersionToLatest(IMigrationContext context) : base(context)
{
}

public override void Migrate()
{
    // If, before the upgrade, there was a published version and a later saved version,
    // after the upgrade the document is listed in an unpublished state.  This query
    // fixes that by declaring that there is a published version and a more recent edited
    // version, since both are already in the database but just not declared as such.
    var updated = Database.Execute(UpdateSql);
    if (updated > 0)
    {
        Context.AddPostMigration();
    }
}
}

Step 16: Fix miscellaneous grid and prevalue errors on upgrade

There are a handful of other data problems when upgrading from Umbraco 7 to Umbraco 8. I won't go into detail about them here. Instead I will link out to the github issues and the solution

We wrote some v8 migrations to solve these problems. You can install the migrations through nuget at ProWorks.Umbraco8.Migrations. You can also see the source code at ProWorks.Umbraco8.Migrations source. There are pull requests open for these issues, but until they are approved, these migrations are what we use to fix these problems.

 

Let us know in the comments if you have any questions or if we need to clear anything up!

Author

Mark Bowser

comments powered by Disqus
back to top