Skip to main content

Outline

At a glance:
  • Platform shift: Transition from legacy ASP.NET Framework to modern ASP.NET Core.
  • Project structure: SDK-style projects simplify dependencies and file management.
  • Configuration: Move from Web.config to layered appsettings.json and the Options Pattern.
  • Hosting: Kestrel and a minimal Program.cs replace Global.asax and IIS-heavy setups.

This module provides an in-depth examination of the fundamental .NET and configuration changes inherent in Optimizely CMS 12 and Commerce 14. Understanding these shifts is essential when transitioning existing solutions or building new ones on the latest Optimizely DXP.

Key .NET changes

1. Project file format (.csproj)

  • Simplified structure: Automatic file inclusion via globbing.
  • SDK-style projects: Projects reference an SDK such as Microsoft.NET.Sdk.Web.
XML
<Project Sdk="Microsoft.NET.Sdk.Web"> <PropertyGroup> <TargetFramework>net8.0</TargetFramework> <ImplicitUsings>enable</ImplicitUsings> <Nullable>enable</Nullable> </PropertyGroup> <ItemGroup> <PackageReference Include="EPiServer.CMS.AspNetCore" Version="12.x.x" /> <PackageReference Include="EPiServer.Commerce.AspNetCore" Version="14.x.x" /> <PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="8.x.x" /> </ItemGroup> </Project>

2. Global tooling and .NET CLI

Bash
# Install Optimizely templates dotnet new install EPiServer.Net.Templates dotnet new epi-cms-empty --name MyOptimizelyCmsProject # Restore packages dotnet restore # Build dotnet build # Run dotnet run

3. Runtime environment and hosting model

The minimal hosting model in Program.cs replaces the Global.asax and Startup.cs pattern from ASP.NET Framework.

C#
var builder = WebApplication.CreateBuilder(args); builder.Services.AddCms(); builder.Services.AddControllersWithViews(); builder.Services.AddRazorPages(); var app = builder.Build(); if (app.Environment.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.UseAuthentication(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapContent(); endpoints.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); endpoints.MapRazorPages(); }); app.Run();

Configuration changes

1. appsettings.json and layered configuration

The flat Web.config is replaced by a layered JSON configuration system. Environment-specific files such as appsettings.Development.json overlay the base file at runtime.

JSON
{ "Logging": { "LogLevel": { "Default": "Information" } }, "Optimizely": { "Cms": { "SiteUrl": "http://localhost:5000" } } }

2. Using the Options Pattern

The Options Pattern replaces direct ConfigurationManager.AppSettings access with strongly-typed classes injected via the DI container.

C#
public class MyCustomSettings { public string Setting1 { get; set; } public int Setting2 { get; set; } } services.Configure<MyCustomSettings>( Configuration.GetSection("MyCustomSection") );

3. Connection strings

Connection strings move from the <connectionStrings> section of Web.config into the ConnectionStrings key in appsettings.json.

JSON
{ "ConnectionStrings": { "EPiServerDB": "YourConnectionStringHere", "EcfSqlConnection": "YourCommerceConnectionStringHere" } }

4. User secrets

Use dotnet user-secrets during development and secure environment variables or key vaults in production to manage sensitive configuration data without committing it to source control.

Secret management by environment

Select a topic to expand and read the details.

Development - dotnet user-secrets

Stores secrets in a local JSON file outside the project directory so they are never accidentally committed to source control. Initialise and set secrets with:

  • dotnet user-secrets init
  • dotnet user-secrets set "ConnectionStrings:EPiServerDB" "..."
Production - environment variables and key vaults

Use platform-level environment variables (e.g., Azure App Service application settings) or a dedicated key vault (e.g., Azure Key Vault) to inject secrets at runtime. The ASP.NET Core configuration system automatically reads environment variables that follow the double-underscore naming convention, for example ConnectionStrings__EPiServerDB.

Conclusion

Migrating to CMS 12 and Commerce 14 introduces a modernised .NET foundation, improved configuration management, and a streamlined hosting model. Mastering these architectural shifts ensures smoother migration and future-ready Optimizely solutions.