Skip to main content

Outline

At a glance
  • Code-first foundation: Architecture is defined in C#, enabling version control and strongly typed models.
  • Inheritance model: Core functionality relies on inheriting from PageData, BlockData, or MediaData base classes.
  • Data integrity: Explicit GUIDs in the [ContentType] attribute prevent data loss during class renaming or refactoring.
  • Property requirements: Properties must be virtual with public accessors to support CMS runtime proxies and database persistence.

Introduction

In Optimizely CMS 12, content architecture is established by defining content types in code. This code-first approach ensures that the content model is version-controlled, strongly typed, and easily deployable. Content types define the schema for data—such as pages, blocks, and media—specifying which properties are available to editors and how the data is structured within the CMS database. This module explores the technical implementation of page and block types, focusing on inheritance, property definition, and best practices for developing a robust content model.

Fundamental Base Classes

All content types in Optimizely CMS 12 must inherit from specific base classes provided in the EPiServer.Core namespace. These base classes provide built-in functionality for content management, including versioning, status handling, and common metadata.

  • PageData: Used for creating page types. A page represents a standalone URL and a node in the hierarchical site structure.
  • BlockData: Used for creating block types. Blocks are modular components that can be used as properties on other content or placed within a ContentArea.
  • MediaData: Used for defining media types, such as images, videos, or documents.

Implementation Pattern: The Common Base Class

It is a best practice to define an abstract base class for a site to encapsulate common properties such as SEO metadata or site-wide configuration.

using EPiServer.Core; using EPiServer.DataAbstraction; using EPiServer.DataAnnotations; using System.ComponentModel.DataAnnotations; namespace MyProject.Models.Pages { public abstract class SitePageData : PageData { [CultureSpecific] [Display( Name = "Meta Title", GroupName = "SEO", Order = 100)] public virtual string MetaTitle { get; set; } [CultureSpecific] [Display( Name = "Meta Description", GroupName = "SEO", Order = 200)] [UIHint(UIHint.Textarea)] public virtual string MetaDescription { get; set; } } }

The [ContentType] Attribute

Classes intended to be content types must be decorated with the [ContentType] attribute. This attribute allows the CMS to discover the class and register it as a content type in the database.

Key Parameters:

  • GUID: A unique identifier for the content type. This is critical for refactoring. If the class is renamed or moved to a different namespace, Optimizely uses the GUID to maintain the connection to the existing data in the database.
  • DisplayName: The name of the content type as it appears to editors in the CMS UI.
  • GroupName: Categorizes the content type in the "New Page" or "New Block" dialogs.
  • Description: Provides helper text for editors explaining the purpose of the type.
  • Order: Determines the sorting order in creation dialogs.
[ContentType( DisplayName = "Standard Article Page", GUID = "B2A123BC-4567-8901-DEF0-ABCDEF123456", Description = "A standard page for news or blog internal articles.", GroupName = "Content")] public class ArticlePage : SitePageData { // Local properties defined here }

Defining Properties

Properties defined within a content type class become editable fields in the CMS UI. To allow Optimizely to manage the data persistence correctly, properties must follow specific rules.

Requirements for Property Definitions
  1. Public Accessors: Properties must have public get and set accessors.
  2. The virtual Keyword: Properties must be declared as virtual. This allows the CMS to create a proxy class during runtime to handle database operations efficiently.

Common Property Attributes:

  • [Display]: Configures the UI label, ordering, and grouping (tabs) in the edit mode.
  • [CultureSpecific]: Enables the property to have unique values for different language branches.
  • [Required]: Ensures that editors must provide a value before saving or publishing.
  • [UIHint]: Provides a hint to the CMS about which editor (e.g., textarea, color picker) to render.

Property Type Mapping

Optimizely CMS 12 supports various .NET types, mapping them to specific CMS property types:

.NET Type CMS Property Type Typical UI Element
string PropertyString (max 255) Textbox
string with [UIHint] PropertyLongString Textarea
XhtmlString PropertyXhtmlString TinyMCE (Rich Text)
int PropertyNumber Integer input
double PropertyFloatNumber Decimal input
bool PropertyBoolean Checkbox
DateTime PropertyDate Date/Time picker
ContentReference PropertyContentReference Content selector
Url PropertyUrl URL selector / link
ContentArea PropertyContentArea Drag-and-drop area
IList<string> PropertyStringList List of text strings

Refactoring Content Types

Maintaining content types over time often requires renaming classes or properties. Because Optimizely is code-first, specific strategies must be employed to avoid data loss.

  1. GUID-based Renaming: If a class is renamed but the GUID remains the same, the system synchronizes the change automatically.
  2. Migration API: For complex changes, developers can implement a class inheriting from MigrationStep to programmatically change the schema.
  3. Data Preservation: When code is deleted, the CMS retains database entries if they contain data, marking them as "missing its code" to prevent accidental loss.

Best Practices

  • Always assign GUIDs: Never rely on class names alone for synchronization.
  • Use GroupNames: Organize properties into tabs (e.g., "Content," "SEO") for a clean editing experience.
  • Leverage UIHints: Ensure editors have the correct tools (e.g., UIHint.Image for image references).
  • Consistent Naming: Adopt a naming convention that aligns with the business domain.
  • Limit Inheritance Depth: High levels of inheritance can make the content model difficult to maintain.

Conclusion

Creating content types and page types is the procedural starting point for any Optimizely CMS 12 project. By defining clear, strongly-typed models in code, developers establish a solid foundation for both the editorial workflow and the rendering logic. Understanding the interplay between base classes, attributes, and property types allows for the creation of sophisticated digital experiences that are both scalable and editor-friendly.