Skip to main content

Outline

At a glance
  • Middleware model: CMS 13 functions as a collection of services hosted within a standard .NET application rather than a standalone wrapper.
  • Pipeline integration: Content delivery relies on specialized middleware that intercepts and routes requests based on database items.
  • Modular stack: Functionality is decoupled into NuGet packages covering hosting abstractions, the core content engine, and the UI shell.
  • DXP readiness: The architecture is built for Azure-native scaling, utilizing distributed caching, blob storage, and Optimizely Graph.

Understanding the architecture of Optimizely CMS 13 requires a shift from viewing the CMS as a standalone application to viewing it as a highly integrated collection of services and middleware within a standard ASP.NET Core (.NET 10) application.

In this page, we will explore the internal layers of the CMS 13 platform and analyze how it hooks into the .NET request pipeline to deliver content.

1. The Multi-Layered Architecture

Optimizely CMS 13 is fundamentally modular. It is distributed via several distinct NuGet packages, each serving a specific role in the hierarchy.

The Hosting Layer (EPiServer.Hosting)

At the base of the stack is the hosting abstraction. This layer is responsible for the initialization lifecycle. When the .NET application starts, the InitializationEngine scans for assemblies containing modules that implement IInitializableModule. This allows the CMS (and your custom extensions) to register dependencies and configure settings before the web host is fully ready.

The Content Engine Layer (EPiServer.CMS.Core)

This is the "brain" of the platform. It handles:

  • Content Repositories: Managing IContent, ContentReference, and versioning.
  • Security & Permissions: The underlying Access Control List (ACL) system.
  • Data Access: Communicating with the SQL database and Blob Storage (typically Azure Blob in a PaaS/DXP environment).
  • Business Logic: Handling events like ContentPublished or ContentMoving.

The Web & UI Layer (EPiServer.CMS.UI)

This layer provides the Edit and Admin interfaces (the "Shell"). In CMS 13, the UI is decoupled from the content engine, allowing it to be updated independently. It utilizes Shell Modules—protected areas of the application typically served from the /EPiServer/ path.

2. Injected: The Role of CMS in a .NET Application

In the world of .NET 10, Optimizely CMS does not "wrap" your application; rather, your application "hosts" the Optimizely services. This integration happens in two key phases within your Startup.cs (or Program.cs in latest .NET templates).

Phase 1: Service Registration (AddCms)

By calling services.AddCms(), you are populating the .NET Dependency Injection (DI) container with hundreds of Optimizely-specific services (e.g., IContentRepository, ISiteDefinitionRepository).

public void ConfigureServices(IServiceCollection services) { services.AddCms() // Injects CMS Core & UI services .AddCmsAspNetIdentity<ApplicationUser>() // Authentication .AddEmbeddedLocalization<Startup>() // Localization .AddVisitorGroups(); // Personalization engine // Database compatibility configuration services.Configure<DataAccessOptions>(options => { options.UpdateDatabaseCompatibilityLevel = true; }); }

Phase 2: The Middleware Pipeline (UseCms)

The real "magic" happens in the Configure method. Optimizely CMS registers specialized middleware that sits in the HTTP request pipeline.

When a request comes in, the CMS middleware checks the requested URL. If the URL matches a content item in the database (e.g., /products/shoe-abc), the CMS intercepts the routing, resolves the appropriate ContentData object, and determines which Controller or Razor Page should handle the rendering.

3. Request Routing and Content Mapping

Standard .NET applications use "Attribute Routing" or "Conventional Routing" (e.g., /{controller}/{action}). Optimizely CMS extends this with Content-based Routing.

  1. URL Entry: A user visits /about-us/our-team.
  2. CMS Middleware: Identifies that /about-us is a Page in the CMS.
  3. Template Resolver: Looks for a Controller or View Component that matches the OurTeamPage content type.
  4. Action Execution: Passes the resolved PageData object directly into the controller action as a parameter.

This allows developers to build standard .NET controllers while the CMS handles the complex URL-to-database mapping.

4. PaaS (DXP) Deployment Architecture

When running in a PaaS (DXP) environment, the architecture scales horizontally. While the CMS code runs within a standard Azure App Service, the supporting infrastructure is distributed:

  • Database: Azure SQL (Managed).
  • Files/Media: Azure Blob Storage (using the EPiServer.Azure provider).
  • Search/Indexing: Optimizely Graph (the primary delivery hub for CMS 13).
  • Caching: Redis (for distributed state and object caching).

Composable vs. Monolithic

In CMS 13, we increasingly see a Remote Website architecture. In this mode, the CMS application acts purely as a "Content API Host" (Headless), while a separate application (e.g., running in Vercel or a separate Azure site) handles the actual rendering. Both are managed under the new Application model in the CMS.

Conclusion

For a technical lead or developer, the key takeaway is that CMS 13 is a middleware framework. You build your .NET application following modern best practices (Dependency Injection, Middleware, Async/Await), and the CMS provides the specialized tools to manage, route, and deliver content within that standard .NET ecosystem.