Creating content types
Outline
- 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 aContentArea. -
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. All concrete page types then inherit from this base rather than directly from PageData.
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 on application startup.
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 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" creation dialogs. -
Description: Provides helper text for editors explaining the purpose of the type. -
Order: Determines the sorting order in creation dialogs.
Important: Always generate and assign a GUID when creating a new content type. Never rely on class names alone for synchronization - renaming a class without a GUID will cause the CMS to treat it as a new type and orphan any existing content.
Defining Properties
Properties defined within a content type class become editable fields in the CMS UI. To allow Optimizely to manage data persistence correctly, all properties must follow two strict rules.
-
Public accessors: Properties must have public
getandsetaccessors. -
The
virtualkeyword: Properties must be declared asvirtual. This allows the CMS to create a proxy class at runtime to handle database operations efficiently.
Common Property Attributes
-
[Display]: Configures the UI label, ordering, and grouping (tabs) in edit mode. -
[CultureSpecific]: Enables the property to hold 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 control to render (e.g., textarea, image picker, color picker).
Property Type Mapping
Optimizely CMS 12 supports various .NET types, mapping them to specific CMS property types and UI controls:
| .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:
- GUID-based Renaming: If a class is renamed but the GUID remains the same, the system synchronizes the change automatically on next startup. No data migration is needed.
-
Migration API: For complex schema changes, developers can implement a class inheriting from
MigrationStepto programmatically alter the content type schema in a controlled, repeatable way. - Data Preservation: When a content type class is deleted, the CMS retains database entries that contain data, marking them as "missing its code" to prevent accidental loss. Entries can be recovered by restoring the class.
Best Practices
Pro tip: Generate all GUIDs before your first deployment. Retrofitting GUIDs onto existing content types in production requires a careful migration step - it is far easier to include them from the start.
- Always assign GUIDs: Never rely on class names alone for synchronization.
- Use GroupNames: Organize properties into named tabs (e.g., "Content," "SEO") for a clean editing experience that scales as the content model grows.
-
Leverage UIHints: Ensure editors have the correct tools for each field, such as
UIHint.Imagefor image references. - Consistent Naming: Adopt a naming convention that aligns with the business domain and remains readable to both developers and editors.
- Limit Inheritance Depth: High levels of inheritance can make the content model difficult to maintain and reason about. Prefer composition using blocks over deep page type hierarchies.
Conclusion
Creating content types and page types is the foundational 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.
