EPiServer  /  CMS January 21, 2013

Upgrading a site from EPiServer CMS 6 to EPiServer 7

EPiServer 7 brings a lot of changes and a new editorial UI. Meanwhile the API is said to be backwards compatible. I've investigated the upgrade experience and found a few interesting things.

I’ve been investigating the upgrade experience from EPiServer CMS version 6 R2 to version 7 lately. Those that have ever upgraded an EPiServer 4 site to version 5 probably know that that’s no easy feat. In fact, I typically recommend my customers to build a new site rather than upgrading. Upgrading from version 5 to 6 on the other hand wasn’t a big deal.

EPiServer 7 features a totally new edit mode and quite a lot of API changes. On the other hand the developers at EPiServer have worked hard to maintain backwards compatibility in a way that should enable us to gradually start using new API features rather than having to rewrite everything just to get an upgraded site to work.

Also, while EPiServer 7 requires .NET 4 instead of .NET 3.5 there hasn’t been any major changes in the underlying platform which EPiServer builds upon, as opposed to the version 4 to 5 upgrade where EPiServer threw out a bunch of custom stuff in favor of standardized components introduced in .NET 2.0 and ASP.NET 2.0.

So, in theory upgrading from 6 R2 to 7 should be a smooth ride. We should expect custom properties to work but not fit into the new design of the edit UI and of course customizations of the old edit UI would have to be replaced. Other than that though, there shouldn’t be any major issues.

Of course we all know that theory and reality rarely meet when dealing with upgrades. Therefor I decided to get my hands dirty and do some upgrading for real. As a first step I decided to set up the standard sample site for EPiServer 6, AlloyTech, and upgrade that to EPiServer 7. Here’s how it went.

Deployment Center and .NET 4

Upgrading through EPiServer’s Deployment Center proved to be a simple next-next-next experience. We simply have to select “Upgrade site with SQL Server database” in the All Actions tab and then select a site to upgrade.

DeploymentCenter

Although I’m sure some will run in to edge cases where there will be problems performing the upgrade I had no problems at all. The only warning that I got was that the “project will have to be compiled after upgrading” which I guess was actually more of a friendly reminder than an actual warning.

After having done the upgrade with Deployment Center I found that it had created a new application pool running .NET 4 in IIS and changed the site’s configuration to use that. Proceeding to open up the project in Visual Studio I ran into a funny little oddity.

Before I even got to open the project though, I was faced with a prompt where I had to choose whether to change the site back to .NET 2.0 or not as the project was still targeting .NET 3.5.

Dialog

Of course I didn’t want that so I clicked no.

Now, remember that EPiServer 7 requires .NET 4 and that Deployment Center had told me I needed to recompile the project. The old Alloy templates are by default configured to target .NET 3.5 and neither myself nor Deployment Center’s upgrade had changed that. Deployment Center had however changed the EPiServer references to their EPiServer 7 versions. Clearly the project shouldn’t compile as it was still targeting an older .NET framework than the referenced EPiServer assemblies.

It did however compile! Of course it didn’t actually, but since I hadn’t changed a single source file Visual Studio didn’t think it actually needed to do anything and reported a successful compilation. Of course, when browsing the site I was met with an angry yellow screen of death, saying “Method not found: 'Boolean EPiServer.Core.PageReference.CompareToIgnoreWorkID(EPiServer.Core.PageReference)'.”.

So, I went ahead and changed the Target Framework to .NET 4.

Fiftyseven compilation errors

Changing target framework made Visual Studio recognize that it actually needed to do some work when I asked it to compile the next time. Now, however, when one could almost expect a successful compilation I was faced with 57 angry errors.

CompilationErrors

Didn’t I say something about EPiServer’s developer having worked hard to maintain a level of backward compatibility with which we should be able to adjust to API changes gradually? As it turned out a lot of the compilation errors were actually warnings about using deprecated methods. Changing the project to not treat warnings as errors brought the compilation error list down to 14 errors.

WarningsAsErrors

The remaining 14 “real” errors could be grouped into three categories.

First of all there were a number of errors due to EPiServer having marked types and methods as obsolete in a way that makes the compiler treats usages of them as errors. In most of those cases fixing the error was easy as pie as EPiServer had also provided a good workaround suggestion in the obsolete attributes.

In one case it wasn’t quite as easy though. As EPiServer 7 supports “any content” in the form of IContent rather than just pages in the form of PageData objects a lot of methods and properties that used to work with PageReferences now expect or return ContentReferences instead. In the AlloyTech code there is a method that looks like this:

SoftLink softLink = (SoftLink)link;
return String.Format("{0} [{1}]", 
    DataFactory.Instance.GetPage(softLink.OwnerPageLink).PageName, 
    softLink.OwnerPageLink.ID);

This little bugger proved slightly more problematic to fix than the other compilation errors due to things having been marked as obsolete. The problem is that SoftLink.PageLink is obsolete and we’re instructed to instead use SoftLink.ContentLink which returns a ContentReference instead of a PageReference. Only, the GetPage method, which I guess one could argue is semi obsolete, requires a PageReference.

Luckily, there’s an easy solution to this. We simply use Get<PageData>() instead of GetPage() as the former is satisfied with a ContentReference as argument. Alternatively we could have constructed a PageReference as the ContentReference has all the required data for doing so, but why bother when we should prefer the new and shiny Get<T>() over the old and dusty GetPage() anyway.

Four compilation errors

Having mostly just followed the instructions from EPiServer, replacing usages of obsolete types and methods with the suggested equivalents I was down to four compilation errors.

Two of those were caused by some code which disabled On Page Edit for a couple of templates. As there isn’t any such thing as (the old) On Page Edit (or DOPE as it’s really called) fixing this simply involved removing the code that didn’t compile.

Finally the last two errors were due to code that instantiated the SiteConfigDB class which no longer has a parameter less constructor and instead requires an IDatabaseHandler as argument. While I can’t say that I’m very familiar with either the SiteConfigDB class or the IDatabaseHandler interface it was quite easy to guess how to fix that – by using the ServiceLocator.

//Before
var siteConfigDB = new SiteConfigDB();

//After
var databaseHandler = ServiceLocator.Current.GetInstance<IDatabaseHandler>();
var siteConfigDB = new SiteConfigDB(databaseHandler);

Build succeeded!

An URL isn't no string no more

Having fixed the last compilation errors I was happy to see that the site’s start page loaded without runtime errors. However, it looked a bit bare as it lacked a logotype. Also, when loading some pages I got a yellow screen of death saying “Unable to cast object of type 'EPiServer.Url' to type 'System.String'”.

In both cases the problem was code that retrieved a URL property’s value from a PageData object using indexer syntax and then casted the value to a string. That worked fine in EPiServer 6 but in 7 the value type for an URL property isn’t a simple string anymore. Instead it’s a Url, as in EPiServer.Url.

So, to get back the logotype and fix runtime errors due to type conversion errors I had to modify such code. For instance, here’s what I did to fix the logotype:

//Before
Logotype.ImageUrl = StartPageData["Logotype"] as string ?? string.Empty;

//After
var logoUrl = StartPageData["Logotype"] as Url;
if (logoUrl != null && !logoUrl.IsEmpty())
{
    Logotype.ImageUrl = logoUrl.ToString();
}

Personally I can’t see any reason why EPiServer couldn’t have added an implicit operator from Url to string which might have made life easier for us. Either way, fixing these issues was straight forward. I could however imagine quite a few projects where developers have written “safe” code that handles when a property’s value isn’t of a specific type. Tracking down bugs due to the changes of value types for properties such as PropertyUrl may prove tiresome in such projects.

Custom properties

According to what I’ve heard and understood custom properties *should* continue to function as before after an upgrade, albeit with custom editing controls displayed in an IFrame. Curious about this, one of the first things I did after successfully upgrading the site was to head over to a Blog item page as I knew that those featured a custom property named BlogTags. Here’s how such a property looked in EPiServer 6’s edit mode:

CustomProperty

Disappointingly I found the property displayed as a regular string in 7’s forms edit mode.

Custom_property_in_7

Analyzing the custom property I realized that it was, given that I’ve worked quite a bit with EPiServer 7, fairly obvious why the custom property control wasn’t used. The old way of connecting a property (as in class inheriting PropertyData or one of its sub types) was to override the CreatePropertyControl method and return an instance of the control that should be used. That’s exactly what was done in this custom property:

public override IPropertyControl CreatePropertyControl()
{
    return new PropertyBlogTagsControl();
}

In EPiServer 7, that doesn’t do anything. Instead I needed to connect the control to the property type in some other way. I did so by adding an EditorHint attribute to both the property class and the control.

[EditorHint("BlogTags")]
public class PropertyBlogTagsControl 
    : Web.PropertyControls.PropertyTextBoxControlBase
//Class definition

[PageDefinitionTypePlugIn]
[EditorHint("BlogTags")]
public class PropertyBlogTags : PropertyString
//Class definition

Et voilà! The property could be edited using a “legacy editor”.

custom_property_with_legacy_editor

Conclusion

After having upgraded the EPiServer 6 version of the Alloy site, twice, I’m surprisingly unsurprised. The experience was pretty much what I had expected as the upgrade did involve fixing some, but not that many, compilation errors. The custom property still worked, albeit after a little adjustment and not exactly looking superb in the context of the sleek new edit UI.

Based on my experiences so far I’d say that upgrading from version 6 to 7 is neither exactly easy nor is it a hellish experience. If one has some experience with EPiServer 7 and the site doesn’t rely on major customizations of the old edit mode I’d account for maybe a days work to perform the initial upgrade of a site.

Reaping the benefits of EPiServer 7’s new edit UI and live preview functionality may however require far more time, much depending on how the site was originally built. If for instance a lot of properties wasn’t rendered using the EPiServer:Property control the site would work but we’d have a fair amount of work in front of us before editors would be able to work outside of forms edit mode.

Likewise, what I’ve described here is the initial steps of the technical upgrade. I still have 43 compiler warnings that should be tended to, configuration files to go through and new coding practices to adopt in the sites code base. Not to mention deployment.

Knowledge about EPiServer 7 is key

I should add that if I hadn’t had worked a lot with EPiServer 7 prior to the upgrade I probably would have had to spend quite a lot more time on the initial upgrade. So, before you think about upgrading anything beyond the simplest of sites, be sure that you have some knowledge and experience with the new version. With that, the basic upgrade shouldn’t be too hard and you can focus on details and making the site nice to work with for editors rather than having to get into a boxing fight with the compiler.

Result

I leave you with this, a screenshot of the good old (well… old at least ;-)) AlloyTech site in EPiServer 7’s new edit UI, Sparrowhawk.

Old_Alloy_in_Sparrohawk

PS. For updates about new posts, sites I find useful and the occasional rant you can follow me on Twitter. You are also most welcome to subscribe to the RSS-feed.

Joel Abrahamsson

Joel Abrahamsson

I'm a passionate web developer and systems architect living in Stockholm, Sweden. I work as CTO for a large media site and enjoy developing with all technologies, especially .NET, Node.js, and ElasticSearch. Read more

Comments

comments powered by Disqus

My book

Want a structured way to learn EPiServer 7 development? Check out my book on Leanpub!

More about EPiServer CMS