Razor Views and ViewComponents
Outline
- Focus: How CMS 12 renders content using Razor Views and ViewComponents
- Key idea: Templates map content to a controller and view (or Razor Pages)
- Developer win: Reusable renderers (partials, layouts, ViewComponents) keep code maintainable
- Editor win: Html.PropertyFor() enables on-page editing in the CMS
For developers working with Optimizely CMS 12 in a Platform-as-a-Service (PaaS) environment, understanding how content templates are rendered is fundamental. CMS 12 leverages standard ASP.NET Core MVC and Razor to display content, giving you robust and flexible mechanisms for building dynamic web experiences. This article breaks down Razor Views, ViewComponents, and the key extension points in the rendering pipeline.
1. Models, Views, and Templates in Optimizely CMS 12
Optimizely CMS 12's rendering flow is rooted in the Model-View-Controller (MVC) pattern. This separation of concerns supports maintainable and scalable implementations:
- Model: Represents data and business logic, independent of the UI.
-
View: Renders the model as HTML - typically a Razor
.cshtmlfile. - Controller: Handles routing and selects which view should render the current content.
How "templates" work in CMS 12: In Optimizely, a "template" means the pairing of a controller action and a Razor view used to render a specific content type. Optimizely uses conventions and template resolution rules to choose the best match for each request.
Alternatively, Razor Pages offer a page-focused approach, pairing a Razor Page file (.cshtml) with a page model (.cshtml.cs) to separate presentation from page-specific logic. By convention, Optimizely MVC projects store renderers in the /Views folder.
2. Views: The Core of Content Display
Views - primarily .cshtml files - are the core display mechanism in CMS 12. They contain HTML markup plus Razor syntax to produce the final output sent to the client.
To keep rendering clean and reusable, developers use five key view constructs:
- Action-specific views: Views scoped to a single controller action for full-page content rendering.
- Partial views: Reusable UI snippets embedded inside other views - ideal for simple blocks with no logic.
- ViewComponents: Self-contained UI components combining logic and a dedicated Razor view.
- Layouts: Shared structural scaffolding for headers, footers, and navigation across pages.
- View models: Strongly-typed models built specifically for a view, decoupling the CMS content type from the rendering layer.
3. HTML Helpers for Dynamic Content
Views contain static HTML markup, but rendering Optimizely properties correctly - and making them editable by editors - depends on using the right helpers.
Pro tip: Always use Html.PropertyFor() to render editable page and block fields. It renders the property value and simultaneously enables on-page editing in the CMS editorial UI - using @Model.Heading directly bypasses on-page editing entirely.
ASP.NET Core MVC and Optimizely CMS together provide a rich set of built-in helper methods. You can also create custom helpers to standardize rendering patterns across your site.
4. ViewComponents for Reusable UI Logic
ViewComponents are ideal when you need reusable UI with real logic - data fetching, composition rules, conditional rendering - that would make a partial view messy or hard to test.
They are especially well-suited for three scenarios:
- Reusable UI elements: Navigation, related content, promotional bands, shopping carts, and similar components that appear across many pages.
- Complex rendering logic: When the UI requires service calls, permission checks, or business rule evaluation before rendering.
- Separation of concerns: Keeps logic out of page controllers and partial views, preserving a clean MVC boundary.
A ViewComponent is a class inheriting from ViewComponent, exposing Invoke() or InvokeAsync() and returning a view result. It prepares data via injected services and hands it to a dedicated Razor view for rendering.
5. Controlling Rendering: Advanced Mechanisms
Optimizely provides mechanisms to control how templates are selected based on context - display options, delivery channels, and tags. Together, these enable adaptive rendering based on content type, display settings, and the channel serving the request.
Template Selection Mechanisms
Select a mechanism to expand and read the details.
TemplateDescriptor ▼
Decorate controllers or views with [TemplateDescriptor] to guide Optimizely's template resolution engine toward the correct renderer for a given content type and context. This is how you register multiple renderings for the same content type.
Tags ▼
Categorize templates for specific rendering contexts using tags such as "Mobile" or "FullWidth". When a page or block is rendered in a context that requests a specific tag, Optimizely selects the matching template over the default one.
TemplateResolver ▼
The TemplateResolver picks the best registered template for a content item given the current context - content type, tags, and display channel. You can extend or replace the default resolver to implement custom template selection logic.
DisplayChannel ▼
Define channel-specific rendering by registering display channels such as web, mobile, or email. Content rendered in a given channel automatically picks up channel-appropriate templates, enabling a single content model to serve multiple delivery surfaces without duplicating markup.
Interactive Practice Ideas
-
Spot the right renderer: Given a page type and a display option ("Full" vs "Teaser"), decide whether to use a new view with a
TemplateDescriptortag, a partial view, or a ViewComponent - and justify the choice. -
PropertyFor vs raw output: Given two snippets -
@Html.PropertyFor(x => x.CurrentPage.Heading)vs@Model.Heading- identify which one enables on-page editing and explain why. - Order-of-logic challenge: Given a scenario where navigation depends on current language and user permissions, choose between a partial view and a ViewComponent and justify the decision.
Conclusion
Mastering Razor Views and ViewComponents is essential for building maintainable, performant, and editor-friendly Optimizely CMS 12 solutions. By understanding MVC, using helpers like Html.PropertyFor(), and applying Optimizely's template selection mechanisms, you can deliver consistent rendering across pages, blocks, channels, and contexts.
