Blocks
Outline
- Concept: Blocks as atomic, reusable UI building blocks
- Architecture: Shared vs. Local (Property) blocks
- Rendering: Partial Views and ViewComponents in ASP.NET Core
Introduction
In Optimizely CMS 12, blocks represent the atomic, reusable building blocks of a digital experience. Unlike pages, which correspond to a specific URL and location in the site hierarchy, blocks are designed to be embedded within other content types. This modularity allows developers to create a library of consistent UI components - such as hero banners, sliders, or call-to-action sections - that editors can use to assemble complex layouts dynamically.
This module explores the technical architecture of blocks, the distinction between shared and local instances, and the modern rendering patterns available in ASP.NET Core.
Defining Block Types
A block type is defined as a .NET class inheriting from EPiServer.Core.BlockData. Just like page types, block classes are decorated with the [ContentType] attribute to define identity and metadata. All properties must be virtual with public accessors to support the CMS proxying system.
Standard Block Definition
Shared Blocks vs. Local (Property) Blocks
Architecturally, blocks can be used in two distinct ways. Choosing the right approach has implications for how content is stored, versioned, and reused across the site.
Block Architecture Options
Select an option to expand and read the details.
Shared Blocks ▼
Shared blocks exist as standalone content items in the Optimizely database. They are located in the Assets pane under "Global" or "This Site" folders, and are managed by editors like any other content.
- Reusability: A single instance of a shared block can be referenced by multiple pages simultaneously. Editing it once updates it everywhere it is used.
-
Storage: They are
IContentitems with their own lifecycle - Published, Draft, and Versioning - independent of any parent page. -
Usage: Typically placed within a
ContentAreaproperty on a page or other block.
Local Blocks (Blocks as Properties) ▼
Local blocks are "property blocks" where the data belongs strictly to the parent page or block. They do not appear in the Assets pane and cannot be independently referenced from other pages.
- Encapsulation: The content is stored as part of the parent's data. It has no independent lifecycle or versioning separate from its parent.
- Storage: Serialized directly into the parent content instance - no additional database row is created for the block itself.
- Usage: Defined as a direct typed property on a page or block model, as shown below.
Pro tip: Use shared blocks only when the content actually needs to be reused across multiple pages. For content unique to a single page, use property (local) blocks to keep the database lean and the editorial model simpler.
Content Areas and AllowedTypes
The ContentArea is the primary property type for creating dynamic, editor-assembled layouts. It allows editors to drag and drop multiple shared blocks into a defined region of a page. To maintain design integrity and prevent editors from placing incompatible content, use the [AllowedTypes] attribute to restrict what can be placed in a specific area.
Rendering Patterns in CMS 12
Optimizely CMS 12 uses the ASP.NET Core rendering engine. Blocks are rendered via one of two patterns - choose based on how much server-side logic the block requires.
1. Partial Views (Fast Rendering)
Partial views are the most efficient method for blocks that require no substantial server-side logic beyond property access. The CMS resolves the view automatically by convention:
- Naming convention: Create a view file with the same name as the block class.
-
Location:
/Views/Shared/Blocks/HeroBannerBlock.cshtml
2. ViewComponents (Logic-Driven Rendering)
If a block requires data from an external API, custom business logic, or complex processing before rendering, a ViewComponent is the correct approach. The component class inherits from BlockComponent<T> and overrides InvokeComponent to build a view model before handing off to the view.
Preview and Templates
By default, blocks are not standalone pages and do not have an independent URL. To allow editors to see what a block looks like during On-Page Editing (OPE), developers must implement a Preview Controller. This controller renders the block within a "preview page" context so editors can review it in isolation.
The TemplateResolver logic determines the correct template to use based on display tags, display channels, and the TemplateDescriptor attribute, enabling different renderings for the same block in different contexts (e.g., full-width vs. sidebar).
Best Practices
-
Assign GUIDs: Always include a unique GUID in the
[ContentType]attribute to prevent data loss during refactoring or class renaming. - Leverage Interfaces: If multiple blocks share common properties (e.g., SEO fields or analytics tracking), define shared interfaces or abstract base classes to avoid duplication.
-
Optimize Property Access: Ensure all properties are marked as
virtualto enable the CMS proxying system for database persistence. -
Use GroupNames: Categorize block types in the "New Block" dialog using
GroupNameon the[ContentType]attribute to help editors find components easily. - Limit Shared Blocks: Use shared blocks only when content actually needs to be reused across pages. For content unique to a single page, use property blocks to minimize database bloat and simplify the editorial model.
Conclusion
Blocks are the fundamental building blocks of a component-driven architecture in Optimizely CMS 12. By mastering the distinction between shared and property blocks and selecting the appropriate rendering pattern - Partial View for simple property-access rendering, ViewComponent for logic-driven scenarios - developers can deliver a flexible, performant, and editor-friendly content management experience.
