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.
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.
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.
-
Public Accessors: Properties must have public
getandsetaccessors. -
The
virtualKeyword: Properties must be declared asvirtual. 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.
- GUID-based Renaming: If a class is renamed but the GUID remains the same, the system synchronizes the change automatically.
-
Migration API: For complex changes, developers can implement a class inheriting from
MigrationStepto programmatically change the schema. - 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.Imagefor 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.
