MasterPage - Recommended Pattern

Recommended usage: treat MasterPage as the shell host. Put the shell markup and ContentPlaceHolder regions in ChildContent, then place page-level Content blocks under ChildComponents. That keeps the familiar Web Forms tag names while behaving more like a Blazor layout with named sections.

How to use it now

  1. Define the shell once with Head and ChildContent.
  2. Keep default placeholder content in the shell so pages can migrate incrementally.
  3. Let each migrated page supply only the Content blocks it actually overrides.

1. Shell component

This is the reusable master-page shell. It owns shared chrome, optional head content, and the placeholder defaults.

<MasterPage>
    <Head>
        <meta name="catalog-shell" content="enabled" />
    </Head>
    <ChildContent>
        <header>...shared chrome...</header>
        <ContentPlaceHolder ID="MainContent" />
        <ContentPlaceHolder ID="Sidebar" />
        <ContentPlaceHolder ID="PageActions">
            Default action from the shell
        </ContentPlaceHolder>
    </ChildContent>
</MasterPage>

2. Child page usage

The page does not rebuild the shell. It just contributes named sections under ChildComponents.

<MasterPage>
    <ChildContent>
        ...shell with ContentPlaceHolder regions...
    </ChildContent>
    <ChildComponents>
        <Content ContentPlaceHolderID="MainContent">
            Page body
        </Content>
        <Content ContentPlaceHolderID="Sidebar">
            Sidebar links
        </Content>
    </ChildComponents>
</MasterPage>

Live Demo: Recommended shell and page contract

This demo shows the new intended pattern directly: the shell owns the layout structure and placeholders, while the page contributes only the named content sections it needs.

Contoso.Site.Master Head-enabled shell

Catalog overview

This content is supplied by the migrated child page and lands in the MainContent slot even though the placeholder renders earlier in the shell.

  • Reusable shell contract
  • Named slot wiring through MasterPageContext
  • Default slot fallback for untouched regions
Sidebar
Recently viewed
  • Quarterly Sales
  • Customer Retention
  • Support Queue
Shared footer and action area from the migrated shell.
What to notice: MainContent and Sidebar are overridden by Content blocks, but PageActions is not, so the shell keeps its default button. That is the new recommended split: shell structure in ChildContent, page sections in ChildComponents, and only the untouched placeholder defaults remain in the shell.
<MasterPage>
    <Head>
        <meta name="sample-masterpage-generated-shell" content="enabled" />
    </Head>
    <ChildContent>
        <ContentPlaceHolder ID="MainContent" />
        <ContentPlaceHolder ID="Sidebar" />
        <ContentPlaceHolder ID="PageActions">
            Default action from Site.Master
        </ContentPlaceHolder>
    </ChildContent>
    <ChildComponents>
        <Content ContentPlaceHolderID="MainContent">
            Child page body
        </Content>
        <Content ContentPlaceHolderID="Sidebar">
            Sidebar links
        </Content>
    </ChildComponents>
</MasterPage>

Live Demo: Head bridge and default slot fallback

The badge below is styled by CSS emitted from the shell's Head content. This is the same migration bridge used for content that originally lived in <head runat="server">. The page also keeps its default action slot because the child page did not supply PageActions.

Head-injected styling is active

Inspect the document head and you'll find <meta name="sample-masterpage-generated-shell" content="enabled">.

Live Demo: Visible parameter

Migrated shells still honor the inherited Visible parameter. Toggling it off suppresses the entire shell and every placeholder inside it.

The shell is currently visible and rendering its slot content.
<MasterPage Visible="@showBridgeShell">
    <ChildContent>
        <ContentPlaceHolder ID="VisibilityStatus">
            Default visibility message.
        </ContentPlaceHolder>
    </ChildContent>
    <ChildComponents>
        <Content ContentPlaceHolderID="VisibilityStatus">
            The shell is currently visible and rendering its slot content.
        </Content>
    </ChildComponents>
</MasterPage>
Recommendation: Use native Blazor layouts for new development. The BWFC master-page bridge is most valuable when you need a runnable migration waypoint before fully adopting @layout, @Body, PageTitle, and HeadContent.
Migration checklist
  1. Keep shared chrome in a reusable shell component.
  2. Move migrated <head runat="server"> content into the shell's Head parameter or native HeadContent.
  3. Leave placeholder defaults in place so pages can migrate incrementally.
  4. When Head and ChildContent are explicit, group page-level Content blocks under <ChildComponents>.
  5. Plan to replace the bridge with native Blazor layouts once migration pressure is gone.