Skip to main content

Outline

At a glance:
  • Razor Pages: Full-page templates when logic is page-focused
  • MVC controllers and views: Page rendering with orchestration and explicit actions
  • ViewComponents: Reusable server-rendered components with encapsulated logic
  • Blocks: Editor-composable content pieces (rendered via partials or ViewComponents)
  • Opal widgets: UI inside the CMS editor surface (not public site rendering)

Overview

Optimizely CMS 12 (PaaS) supports multiple rendering choices for developer-built UI and content presentation. Each option has trade-offs in scope, reusability, complexity, and where it runs (public website vs. CMS editor UI).

Rule of thumb: Pick the simplest option that fits the job. Complexity is not a flex - it is a recurring subscription.

Decision Guide

Work through these questions in order to identify the right rendering approach.

1. Where does this UI run?

Public site (Razor Pages / MVC / blocks / ViewComponents) vs. CMS editor or admin UI (Opal widgets). This question alone eliminates most of the list.

2. Is it a full page route or a piece inside a page?

Full page route = use a page template (Razor Page or MVC controller). Piece inside a page = use a block, partial view, or ViewComponent.

3. Does the piece need server-side logic?

Yes (data fetching, conditional rendering, injected services) = prefer a ViewComponent. No = a partial view or DisplayTemplate is usually sufficient and simpler.

4. Does an editor need to reuse or compose it?

Yes = model it as a block so editors can discover, drag, and reuse it via a ContentArea, then choose the rendering approach (partial or ViewComponent) separately.

Rendering Options

Each option below explains what it is, when to choose it, and the typical drawbacks in CMS 12 PaaS.

Options

Select an option to expand and read the details.

Razor Pages

When to choose: When the template behaves like a full standalone page handler and you want convention-driven rendering with minimal boilerplate.

What it is: A Razor Page pairs a .cshtml file with an associated .cshtml.cs page model. CMS 12 can treat this as a template and bind routed content accordingly.

C#
// Sample Razor Page Model public class ExamplePageModel : RazorPageModel<ExampleContent> { public void OnGet() { // Page logic } }

Drawbacks:

  • Not ideal for reusable pieces that compose into larger pages.
  • Not designed for block rendering inside a ContentArea.
MVC Controllers and Views

When to choose: When page rendering needs orchestration (building view models, loading related content, handling variations), when you want clear separation of concerns, or when you reuse controller behavior across page types via base controllers.

C#
public class StandardPageController : PageController<StandardPage> { public IActionResult Index(StandardPage currentPage) { return View(currentPage); } }

Drawbacks:

  • More boilerplate than Razor Pages.
  • Can be overkill for very simple page templates with no orchestration logic.
ViewComponents

When to choose: When rendering reusable components or blocks with logic, or when you need clean encapsulation of rendering logic that runs inside pages.

In CMS 12: Blocks often render through ViewComponents. If a block needs logic - for example, loading related content or computing a view model - a ViewComponent is the right tool.

C#
public class TeaserBlockViewComponent : BlockComponent<TeaserBlock> { protected override IViewComponentResult InvokeComponent(TeaserBlock currentBlock) { return View(currentBlock); } }

Drawbacks:

  • Slightly more setup than a simple partial view.
  • If there is no logic involved, a partial view or DisplayTemplate is simpler and equally correct.
Blocks

When to choose: When editors need reusable pieces that can be composed into pages via a ContentArea and editorial page assembly.

What blocks are: Smaller content types inheriting from BlockData that render inside pages. They are content model definitions, not standalone page templates.

Rendering blocks - choose based on logic:
  • Partial view / DisplayTemplate: Best when you only need markup and simple formatting.
  • ViewComponent: Best when you need logic to load, compute, or build a view model before rendering.

Important distinction:

  • Block type = the content definition (data model).
  • Block rendering = the presentation choice (partial/DisplayTemplate vs. ViewComponent). These are separate decisions.
Opal Widgets

When to choose: When you need custom UI inside the CMS editor or admin interface. Not for public-facing website rendering.

What Opal widgets are: Extensions to the CMS UI - panels, dashboard tools, workflow helpers, or custom editing experiences. They run inside the editor surface, not on the public site.

Do not mix these up: Blocks, Razor/MVC, and ViewComponents render the public website. Opal widgets enhance the CMS editor and admin experience. They are entirely separate concerns.

How to Choose Among These

Public Website Rendering

  • Razor Pages for simple page templates with page-focused logic and minimal boilerplate.
  • MVC controllers and views for complex orchestration, view model construction, and explicit control flow.
  • ViewComponents for reusable UI segments that need server-side logic.
  • Blocks when editors need composable, reusable content pieces assembled via a ContentArea.

CMS Editor and Admin UI

  • Opal widgets when enhancing CMS screens and editor productivity - not for public rendering.

Conclusion

The right choice depends on scope (page vs. component), whether rendering needs logic, how much reuse you need, and whether the UI lives on the public site or inside the CMS editor. Keep it simple: page templates for pages, blocks for editorial composition, ViewComponents for logic-driven pieces, and Opal widgets only for CMS UI extensions.