Skip to main content

Outline

At a glance
  • Foundation first: Target .NET 10 and unify NuGet packages before touching business logic.
  • Identity gate: Prioritize Opti ID and service registration to ensure administrative access.
  • Type evolution: Systematically replace legacy singletons and types like PageReference with modern equivalents.
  • Feature timing: Defer complex search and UI refactors until the core application model is stable.

Modernizing an application from Optimizely CMS 12 to CMS 13 requires a phased refactoring strategy. While the migration is fundamentally more straightforward than previous major version jumps, the service-bound nature of the new architecture dictates a specific order of operations. Technical teams must prioritize infrastructure and identity to establish a working environment before tackling feature-level refactoring and legacy code retirement.

1. Phase 1: Critical Infrastructure and Gating Updates

Refactoring must begin at the project definition level. Attempting to address business logic or UI extensions before updating the underlying runtime will result in widespread compilation errors and dependency conflicts.

1.1 .NET 10 Runtime Targeting

The initial refactor target is the TargetFramework within all .csproj files. This is the mandatory foundation for all subsequent package updates.

<Project Sdk="Microsoft.NET.Sdk.Web"> <PropertyGroup> <TargetFramework>net10.0</TargetFramework> <LangVersion>latest</LangVersion> </PropertyGroup> </Project>

1.2. NuGet Package Unification

Following the framework update, all Optimizely dependencies must transition to the 13.x release series. This includes core packages and the mandatory identity decoupling package.

  • Core CMS: EPiServer.CMS and EPiServer.CMS.UI.Core
  • Identity: Decouple local identity by adding EPiServer.Cms.UI.OptimizelyIdentity
  • Infrastructure: Ensure Microsoft.EntityFrameworkCore references match the .NET 10 runtime requirements (version 10.0.x).

2. Phase 2: Startup Logic and Identity Orchestration

Once the infrastructure is compile-ready, the service registration pipeline within Program.cs or Startup.cs requires refactoring to accommodate the new platform identity model.

Centralized Identity Registration

Identity management refactoring is a high-priority step because it gates access to the administrative interface. The move to Opti ID necessitates the removal of legacy virtual role providers and the adoption of the AddOptimizelyIdentity extension.

public void ConfigureServices(IServiceCollection services) { // High-priority refactor: Shift to centralized identity services.AddOptimizelyIdentity(useAsDefault: true); // Feature enablement: Visitor Groups now require explicit registration services.AddVisitorGroups(); // Database stability: Force compatibility level updates services.Configure<DataAccessOptions>(options => { options.UpdateDatabaseCompatibilityLevel = true; }); }

3. Phase 3: Application Model and Reference Refactoring

After the application is operational and accessible via Opti ID, the focus shifts to internal architectural cleanup. These updates can be handled later in the cycle but must be completed before the solution is considered stable.

Application Resolver Implementation

Replacing SiteDefinition.Current usage is a material refactor. The legacy singleton pattern is retired in favor of the asynchronous IApplicationResolver.

  • Update First: Remove all static references to SiteDefinition.Current.
  • Update Later/In Parallel: Refactor services to inject IApplicationResolver and migrate hostname mappings to the new Application model.

Type Unification (PageReference to ContentReference)

A pervasive refactor involves the removal of the PageReference type.

  • Strategy: Systematically replace all instances of PageReference with ContentReference.
  • Property Mapping: Update class definitions where PageLink was used, mapping them to the more generic ContentLink property.

4. Phase 4: Feature-Level Migrations (Search and UI)

The final phase involves transitioning complex feature sets that have been decommissioned or replaced. Due to the refactoring effort involved, these are often planned for the latter half of the upgrade cycle.

  • Search and Navigation Decommissioning: Transitions from legacy SearchClient logic to Optimizely Graph should occur after content synchronization is verified. This ensures search template refactors have a reliable GraphQL data source.
  • UI Shell Tag Helpers: Custom administrative layouts must be refactored to utilize the <platform-navigation /> tag helper to ensure alignment with the new identity bar.

Conclusion

Successful refactoring for CMS 13 is governed by dependency priority. By addressing the .NET 10 runtime and identity gates immediately, technical teams establish a stable sandbox for the later work of API cleanup and search refactoring. This prioritized approach ensures that critical system failures are identified early in the upgrade cycle, allowing for a focused transition toward the fully integrated Optimizely One ecosystem.