Exam Area: Area 4 – Framework Components (15%)
Source: https://academy.optimizely.com/student/path/3128969/activity/4970338 | /4970339 | /4970342
Published: Feb 16–17, 2026
- Where TinyMCE shows up: Automatically for
XhtmlStringproperties in the CMS UI.- Primary lever: Centralized configuration via DI using
IConfigureOptions<TinyMceConfiguration>.- Scope hierarchy:
Default()(global) → content type → property-specific (most specific wins).- Toolbar = what editors see; valid_elements = what HTML can be stored.
- PaaS reality: Configuration is code-driven, promoted via CI/CD (treat changes like schema evolution).
TinyMCE is the default editor for XhtmlString properties. Integration is automatic — no View configuration required.
// XhtmlString property → TinyMCE auto-attached in Edit mode
[Display(Name = "Main body", GroupName = SystemTabNames.Content, Order = 100)]
public virtual XhtmlString MainBody { get; set; }
using EPiServer.Cms.TinyMce.Core;
using Microsoft.Extensions.Options;
public class ConfigureTinyMceOptions : IConfigureOptions<TinyMceConfiguration>
{
public void Configure(TinyMceConfiguration config)
{
config.Default()
.AddPlugin("lists")
.AddPlugin("link")
.Toolbar("bold italic | bullist numlist | link");
}
}
// Registration in Program.cs
builder.Services.ConfigureOptions<ConfigureTinyMceOptions>();
// Global default — applies to ALL XhtmlString properties
config.Default()
.Toolbar("bold italic underline")
.AddPlugin("link");
// Content-type specific — applies to all XhtmlString in StandardPage
config.For<StandardPage>()
.Toolbar("bold italic | link");
// Property-level — most specific, overrides everything above
config.For<StandardPage>(p => p.MainBody)
.Toolbar("bold italic underline | link image");
// Summary field — minimal
config.For<ArticlePage>(p => p.Summary)
.Toolbar("bold italic | epi-link");
Resolution order: Global Default → Content-type → Property (most specific wins).
config.Default()
.AddPlugin("code")
.AddPlugin("table")
.AddPlugin("lists")
.AddPlugin("image")
.Toolbar("bold italic | table | code");
Rule: A toolbar button requires its plugin to be enabled — adding a button without the plugin is a no-op.
services.Configure<TinyMceConfiguration>(config =>
{
config.Default()
.AddEpiserverSupport()
.Toolbar("formatselect styleselect | bold italic underline | epi-link image")
.AppendToolbar("code table");
});
Toolbar() — replaces the toolbarAppendToolbar() — extends the existing toolbarconfig.For<StandardPage>(t => t.MainBody)
.Toolbar("styleselect | bold italic")
.StyleFormats(
new {
title = "Lead Paragraph",
block = "p",
classes = "lead"
},
new {
title = "Callout",
block = "div",
classes = "callout-box"
},
new {
title = "Important",
inline = "span",
classes = "text-important"
}
);
Note: Every CSS class referenced in
StyleFormatsmust exist in the frontend stylesheet.StyleFormats()replaces default styles — merge explicitly if needed.
config.Default()
.AddSetting("valid_elements", "p,strong/b,em/i,ul,ol,li,a[href|target]");
Restricts stored HTML to specific elements — essential for structured design systems.
config.Default()
.ContentCss("/Static/css/editor.css")
.BodyClass("mce-content-body");
[TinyMceSettings(
Toolbar = "bold italic underline",
Plugins = "lists link")]
public virtual XhtmlString Summary { get; set; }
Use sparingly — centralized
IConfigureOptionsis preferred for large solutions.
<!-- /lang/en.xml -->
<languages>
<language name="English" id="en">
<tinymce>
<editorstyles>
<lead-paragraph>Lead paragraph</lead-paragraph>
<callout>Callout</callout>
</editorstyles>
</tinymce>
</language>
</languages>
XhtmlString)IConfigureOptions<TinyMceConfiguration>)AppendToolbar() differ from Toolbar()? (Toolbar() replaces; AppendToolbar() extends)StyleFormats() do? (Defines structured formatting options mapped to frontend CSS classes)valid_elements setting used for? (Restrict allowed HTML tags/attributes in stored content)