ContentPlaceHolder¶
The ContentPlaceHolder component emulates the ASP.NET Web Forms <asp:ContentPlaceHolder> control. A ContentPlaceHolder defines a region in a master page where child pages inject content using Content controls. This component bridges Web Forms master page syntax with Blazor's layout system.
Original Microsoft documentation: https://docs.microsoft.com/en-us/dotnet/api/system.web.ui.webcontrols.contentplaceholder
Features Supported in Blazor¶
ID— identifier to match with Content control's ContentPlaceHolderIDChildContent— default content to display if no Content control provides a replacement- Auto-registration with parent MasterPage component
- Renders content provided by child pages via Content controls, or falls back to default ChildContent
Web Forms Features NOT Supported¶
- Multiple master pages cascading placeholders (use nested layouts in Blazor instead)
- Master page inheritance chains with placeholders
Web Forms Declarative Syntax¶
<!-- Site.Master -->
<%@ Master Language="C#" %>
<html>
<head>
<title><%: Page.Title %></title>
</head>
<body>
<div class="header">
<h1>My Website</h1>
</div>
<asp:ContentPlaceHolder ID="MainContent" runat="server">
<p>Default content if no page overrides this placeholder</p>
</asp:ContentPlaceHolder>
<div class="footer">
<p>© 2024 My Company</p>
</div>
</body>
</html>
Blazor Syntax¶
ContentPlaceHolder components are placed within the ChildContent of a MasterPage component. They automatically register with the parent MasterPage.
Basic ContentPlaceHolder with Default Content¶
<MasterPage>
<ChildContent>
<div class="header">
<h1>My Website</h1>
</div>
<ContentPlaceHolder ID="MainContent">
<p>This is the default content for the main area.</p>
</ContentPlaceHolder>
<div class="footer">
<p>© 2024 My Company</p>
</div>
</ChildContent>
</MasterPage>
Multiple ContentPlaceHolders¶
<MasterPage>
<ChildContent>
<header>
<ContentPlaceHolder ID="PageTitle">
<h1>Default Title</h1>
</ContentPlaceHolder>
</header>
<aside>
<ContentPlaceHolder ID="Sidebar">
<nav>
<ul>
<li><a href="/">Home</a></li>
<li><a href="/about">About</a></li>
</ul>
</nav>
</ContentPlaceHolder>
</aside>
<main>
<ContentPlaceHolder ID="MainContent">
<p>Main content goes here</p>
</ContentPlaceHolder>
</main>
</ChildContent>
</MasterPage>
Empty ContentPlaceHolder with Content Requirement¶
<MasterPage>
<ChildContent>
<div class="container">
<ContentPlaceHolder ID="Content">
<!-- No default content - pages must provide content -->
</ContentPlaceHolder>
</div>
</ChildContent>
</MasterPage>
ContentPlaceHolder with Styled Default Content¶
<MasterPage>
<ChildContent>
<div class="main">
<ContentPlaceHolder ID="MainContent">
<div class="alert alert-info">
<p>No custom content provided. This is the default message.</p>
</div>
</ContentPlaceHolder>
</div>
</ChildContent>
</MasterPage>
HTML Output¶
ContentPlaceHolder renders either the content provided by a child page's Content control, or its default ChildContent if no matching Content is found.
Blazor Input (with matching Content):
<MasterPage>
<ChildContent>
<ContentPlaceHolder ID="Main">
<p>Default</p>
</ContentPlaceHolder>
</ChildContent>
<Content ContentPlaceHolderID="Main">
<p>Custom Content</p>
</Content>
</MasterPage>
Rendered HTML:
Blazor Input (no matching Content):
<MasterPage>
<ChildContent>
<ContentPlaceHolder ID="Main">
<p>Default</p>
</ContentPlaceHolder>
</ChildContent>
</MasterPage>
Rendered HTML:
Parameters¶
| Parameter | Type | Default | Description |
|---|---|---|---|
ID |
string | null | The unique identifier for this placeholder; used by Content controls to match ContentPlaceHolderID |
ChildContent |
RenderFragment | null | The default content to render if no Content control provides a replacement |
Visible |
bool | true | Controls whether the placeholder and its content are rendered (inherited from BaseWebFormsComponent) |
Migration Notes¶
When migrating from Web Forms to Blazor:
- Remove
asp:prefix andrunat="server"— Change<asp:ContentPlaceHolder>to<ContentPlaceHolder> - Keep the ID — The ID attribute is used the same way to match placeholders with Content controls
- Place within MasterPage — ContentPlaceHolder must be a child of a MasterPage component
- Default content becomes ChildContent — What was inside the Web Forms tag becomes the ChildContent of the component
Before (Web Forms)¶
<!-- Site.Master -->
<%@ Master Language="C#" %>
<html>
<body>
<div class="sidebar">
<asp:ContentPlaceHolder ID="SidebarContent" runat="server">
<p>Default sidebar</p>
</asp:ContentPlaceHolder>
</div>
<div class="main">
<asp:ContentPlaceHolder ID="MainContent" runat="server">
<p>Default main area</p>
</asp:ContentPlaceHolder>
</div>
</body>
</html>
<!-- MyPage.aspx -->
<%@ Page MasterPageFile="~/Site.Master" %>
<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
<h1>My Page</h1>
<p>My content here</p>
</asp:Content>
After (Blazor)¶
<!-- MasterLayout.razor -->
<MasterPage>
<ChildContent>
<div class="sidebar">
<ContentPlaceHolder ID="SidebarContent">
<p>Default sidebar</p>
</ContentPlaceHolder>
</div>
<div class="main">
<ContentPlaceHolder ID="MainContent">
<p>Default main area</p>
</ContentPlaceHolder>
</div>
</ChildContent>
</MasterPage>
<!-- MyPage.razor -->
<MasterPage>
<ChildContent>
<div class="sidebar">
<ContentPlaceHolder ID="SidebarContent">
<p>Default sidebar</p>
</ContentPlaceHolder>
</div>
<div class="main">
<ContentPlaceHolder ID="MainContent">
<p>Default main area</p>
</ContentPlaceHolder>
</div>
</ChildContent>
<Content ContentPlaceHolderID="MainContent">
<h1>My Page</h1>
<p>My content here</p>
</Content>
</MasterPage>
See Also¶
- Content — Provides content to fill ContentPlaceHolder regions
- MasterPage — Container for master page layouts
- Migration: Master Pages — Comprehensive master page migration guide