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:
REST API — Always Included
The REST API is now always included in CMS 13 projects — no separate opt-in needed which includes **Application Management API** (experimental) — that lets you manage applications programmatically
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.
Comments