CMS 13 Preview 4 — Upgrading from Preview 3
This is the third post in a series where I use the Alloy template as a reference to walk through each CMS 13 preview. The first post covered upgrading from CMS 12 to Preview 2, and the second looked at the key changes in Preview 3. If you're following along, pick up where we left off.
Preview 4 is out. The package bump is easy enough, but there's an API change around how you resolve the start page that'll ripple through your code. Here's what to change and what's worth knowing about.
Step 1: Update Packages
Bump your package references from preview3 to preview4:
<PackageReference Include="EPiServer.CMS" Version="13.0.0-preview4" />
<PackageReference Include="EPiServer.CMS.UI.AspNetIdentity" Version="13.0.0-preview4" />
<PackageReference Include="Optimizely.Graph.Cms" Version="13.0.0-preview4" />
Known Issue: Database Schema Upgrade from Older CMS 12 Versions
If you're upgrading directly from an older CMS 12 version (e.g. 12.34.1 or earlier) to a CMS 13 preview and not from preview3 (which this article assumes), the database schema migration may fail with an error like:Column names in each table must be unique. Column name 'Failed' in table 'dbo.tblNotificationMessage' is specified more than once.
This happens because certain columns were added in later CMS 12 releases, and the CMS 13 migration scripts don't check whether they already exist before trying to add them.Step 2: Resolving the Start Page
In Preview 3, Alloy template resolved the start page by casting to Website and accessing RoutingEntryPoint. In Preview 4, the simplest approach is to use ContentReference.StartPage directly — no need to go through IApplicationResolver in most cases.
Before (Preview 3)
var website = _applicationResolver.GetByContext() as Website;
var startPageContentLink = website?.RoutingEntryPoint;
After (Preview 4)
var startPageContentLink = ContentReference.StartPage;
In the Alloy template this simplified things across several files by using ContentReference.StartPage
- PageViewContextFactory.cs — CreateLayoutModel
- ContentLocator.cs — GetContactPages
- PreviewController.cs — the Index action
- StartPageController.cs — the Index action
- Breadcrumbs.cshtml and Header.cshtml — same change
If you do need more control, IRoutableApplication with its EntryPoint property is still available as an alternative.
The SiteDefinition migration keeps getting refined. Issues with default application provisioning and hostname resolution between preview and view modes from earlier previews have been sorted out.
Step 3: DAM Integration (optional)
Preview 4 adds a new package for Optimizely DAM integration. Its important to call out that even though DAM is a fundamental piece of CMS 13 it is possible to run without it. CMS still can store assets in te traditional sense.
Similar to CMS 12 the DAM configuration is handled using options directly requiring an application to be created in CMP from which the credentials can be retrieved for configuration in CMS. You'll also need the SSO ID which can be found under Settings \ Organization \ General in CMP.
The DAM integration no longer talks to the CMP REST API directly. Instead it's built on External Sources, which means DAM assets need to be indexed into the Optimizely Graph instance connected to your CMS. So before wiring up the code below, make sure you have Optimizely Graph set up, then contact Optimizely Support to connect DAM to your Graph instance. The onboarding steps — selecting your DAM instance, activating asset types — follow the same process as CMS SaaS and are documented in the Onboard DAM to CMS guide. Updated documentation specific to CMS 13 will be available at release. Once that's done, Content Manager can be used to discover and pick DAM assets directly from the editing UI.
Add the package:
<PackageReference Include="EPiServer.Cms.DamIntegration.UI" Version="13.0.0-preview4" />
Register the DAM UI in Startup.cs:
services.AddDamUI();
Add the DAM HTML helpers namespace to Views/_ViewImports.cshtml:
@using EPiServer.Cms.DamIntegration.UI.Helpers
This gives you access to helpers like RenderTagWithMetadata(...) for rendering DAM assets. Note that the epi-property tag helper you're already using comes from EPiServer.Cms.AspNetCore.TagHelpers, which should already be registered in your _ViewImports.cshtml via @addTagHelper.
Then configure your CMP credentials (note that these have defaults, included here for transparency) in appsettings.json:
"Optimizely": {
"Cms": {
"DamUI": {
"Endpoint": "https://cmp.optimizely.com",
"SsoId": "<your-sso-id>",
"NavigationUrl": "https://cmp.optimizely.com/cloud/library"
}
},
"Cmp": {
"Client": {
"TokenUrl": "https://accounts.cmp.optimizely.com/o/oauth2/v1/token",
"ApiUrl": "https://api.cmp.optimizely.com/v3/",
"ClientId": "<your-client-id>",
"ClientSecret": "<your-client-secret>"
}
}
}
The DAM picker now also supports multi-select, which is a nice improvement for editors working with lots of media.
Migrating from CMS 12 DAM Integration
For the GA release of CMS 13, a standalone migration package will be available that converts the CMS 12-style DAM integration to the new one. This package will handle the migration of existing DAM asset references so that they work with the new EPiServer.Cms.DamIntegration.UI package.
The first version of the migration package will support:
- ContentReference properties
- IList<ContentReference> properties
Support for additional property types will be added in future releases.
Using DAM Assets in Your Content
To use DAM assets on a page, add a ContentReference property with the UIHint.Image hint:
using EPiServer.Web;
using System.ComponentModel.DataAnnotations;
public class DamExamplePage : StandardPage
{
[Display(GroupName = Globals.GroupNames.Content)]
[UIHint(UIHint.Image)]
public virtual ContentReference Image { get; set; }
}
In the view, render it with the epi-property tag helper — same pattern as any other CMS property:
<img epi-property="@Model.CurrentPage.Image" />
Step 4: Audiences (optional)
Audiences are a separate package in CMS 13. If you were using services.AddVisitorGroups() in Preview 3, you'll need to add the new NuGet package and update your service registration.
Add the package:
<PackageReference Include="EPiServer.Cms.UI.VisitorGroups" Version="13.0.0-preview4" />
Then update your Startup.cs — the old AddVisitorGroups() call is replaced with two separate registrations:
using EPiServer.Cms.UI.VisitorGroups;
services.AddVisitorGroupsMvc().AddVisitorGroupsUI();
A few audience-related bugs have also been fixed: the policy-not-found error is gone, Geographic Location criteria works, and context menu positioning for personalized groups has been corrected.
What Else Is New in Preview 4
A few things worth knowing about beyond the upgrade steps:
Graph .NET SDK
There's a new .NET SDK for Optimizely Graph with a fluent API covering facets, caching, auth, tracking, and object-to-Graph field mapping. Extensibility points have also been added to ContentGraph.CMS so you can hook into the indexing pipeline.
Improved Migration from SiteDefinition
The migration from SiteDefinition to the Application Model has been improved. Creating in-process websites via the settings UI works again, and typed content types now show up correctly when picking the start page for an application.
For the full list of changes, check the official release notes.
Great series, Robert - following this closely as we're in the middle of our own CMS 13 migration.
One thing I haven't seen covered yet: any idea when a Commerce 15 preview targeting CMS 13 / .NET 10 might land? We're currently blocked because Commerce 14.45.0 still has a hard dependency on ISynchronizedObjectInstanceCache, which got removed in Framework 13.0.0.0 boots up with a lovely AggregateException full of ReflectionTypeLoadExceptions.
Would really help with planning if there's even a rough ETA or a preview feed we could point at.
Piotr
@Piotr thank you! Please refer to the new assembly EPiServer.Cache, EPiServer.Cache 13.0.0-preview4 - Optimizely Nuget. It should contain the ISynchronizedObjectInstanceCache. As we get closer to the GA release more documentation will come online. Regarding Commerce I dont want to speak on their behalf, but I think it is safe to assume that they are working on something.
Hi @Piotr, thank you for consistently staying up to date with Optimizely CMS and Commerce. The Commerce team is preparing to release the first preview of Commerce 15 - fully compatible with CMS 13 (with CMS13 preview4 packages as dependencies) - in about one week. Further details will be shared later. We appreciate your support and patience.
With preview3 we were fine just by installing EPiServer.CMS and EPiServer.Cms.UI.AspNetIdentity.
But with preview4 there are a bunch of version conflicts that forces us to explicitly install specific packages in a certain order. Just wanted to check if this is intentional?
These packages had to be added explicitly in order to build:
Only after these packages were explictly installed, we could update EPiServer.Cms.
@Johan this is unintentional. I'll take a task back to the team to investigate. Can you share which dependencies you had in your project before the update so we can try to reproduce it? Do you have multiple projects in the same solution?
@Johan that is surprising. This are the dependencies in the csproj file that I have for the Alloy project I have upgraded from CMS 12 templates. Note that I have chosen to Content Manager, DAM integration and Graph. What does your setup look like? Are you running an Alloy template or something else?
@Johan I removed ContentManager, Dam integration and Graph. And I also cleaned my binary files and the modules folder. After rebuilding everything from scratch it compiles and runs as it should. Looking forward to some more information from you that we can forward to the team looking at this issue.
Here are our package references for preview3:
Step1: Trying to bump just EPiServer.CMS gives us the following error:
Version conflict detected for EPiServer.UI. Install/reference EPiServer.UI 13.0.0-preview4 directly to project alloy13preview to resolve this issue.
alloy13preview -> EPiServer.Cms 13.0.0-preview4 -> EPiServer.Cms.TinyMce 13.0.0-preview4 -> EPiServer.Cms.Shell.UI 13.0.0-preview4 -> EPiServer.UI (= 13.0.0-preview4)
alloy13preview -> EPiServer.Cms.UI.AspNetIdentity 13.0.0-preview3 -> EPiServer.UI (= 13.0.0-preview3).
Step 2: Trying to install EPiServer.UI directly gives us the following error:
Version conflict detected for EPiServer.ImageLibrary.ImageSharp. Install/reference EPiServer.ImageLibrary.ImageSharp 13.0.0-preview4 directly to project alloy13preview to resolve this issue.
alloy13preview -> EPiServer.UI 13.0.0-preview4 -> EPiServer.Shell.UI 13.0.0-preview4 -> EPiServer.Shell 13.0.0-preview4 -> EPiServer.ImageLibrary.ImageSharp (= 13.0.0-preview4)
alloy13preview -> EPiServer.Cms 13.0.0-preview3 -> EPiServer.ImageLibrary.ImageSharp (= 13.0.0-preview3).
Step 3: Trying to install EPiServer.ImageLibrary.ImageSharp works.
Step 4: Trying to install EPiServer.UI works.
Step 5: Trying to bump EPiServer.CMS again gives us the following error:
Version conflict detected for EPiServer.Shell.UI. Install/reference EPiServer.Shell.UI 13.0.0-preview4 directly to project alloy13preview to resolve this issue.
alloy13preview -> EPiServer.Cms 13.0.0-preview4 -> EPiServer.Cms.UI 13.0.0-preview4 -> EPiServer.Cms.UI.Core 13.0.0-preview4 -> EPiServer.Shell.UI (= 13.0.0-preview4)
alloy13preview -> EPiServer.UI 13.0.0-preview3 -> EPiServer.Shell.UI (= 13.0.0-preview3).
And so on and so on....
Do note that I use the interactive "Nuget package manager" in Visual Studio, I don't just swap the numbers in the csproj, fwiw.
Hi @Johan, could you try upgrading both CMS and Cms.UI.AspNetIdentity from preview 3 to preview 4. From your steps, it looks like your Cms.UI.AspNetIdentity is still on the preview3 version
alloy13preview -> EPiServer.Cms 13.0.0-preview4 -> EPiServer.Cms.TinyMce 13.0.0-preview4 -> EPiServer.Cms.Shell.UI 13.0.0-preview4 -> EPiServer.UI (= 13.0.0-preview4)alloy13preview -> EPiServer.Cms.UI.AspNetIdentity 13.0.0-preview3 -> EPiServer.UI (= 13.0.0-preview3).Is customizing Dojo plugins still a nightmare?
Thanks! @Phu
Bumping both packages at the same time made wonders! 🎉
@Manoj that is an excellent question. I would encourage you to submit it to the Webinar that takes place tomorrow, see Optimizely CMS 13 and Commerce Connect 15 Technical Webinar - Optimizely
@Robert Thank you for the heads-up! I am looking forward to the webinar tomorrow and can't wait to submit questions.
@Piotr no need to wait to submit. There is a form to submit questions on the invite. You can find it at CMS 13 Technical Webinar. Pre submitted questions will be prioritized.