Skip to content

Provisioning Engine (Client-Side Pages) - Vertical section controls exported with wrong Column index #1231

@nicolaor

Description

@nicolaor

Provisioning Engine (Client-Side Pages) — Vertical section controls exported with wrong Column index

Describe the bug

When exporting a SharePoint page that contains a vertical section layout (e.g. TwoColumnRightVerticalSection) to a PnP provisioning template, controls in the vertical section column are assigned an incorrect Column index. This causes the controls to be placed in the wrong column when the template is later applied to a new site.

The root cause is in ClientSidePageContentsHelper.cs where the column index for vertical section controls is computed using:

Column = column.IsVerticalSectionColumn ? section.Columns.IndexOf(column) + 1 : column.Order

The Columns list order is determined by HTML parsing order, which is not guaranteed. The vertical section column (layoutIndex=2) can appear at any position in the Columns list — for example at index 0 — resulting in Column = 1.

During import (in ObjectClientSidePages.cs), the CanvasSection constructor creates columns in a fixed order for each template type. For TwoColumnRightVerticalSection, the columns are always created as:

  1. Narrow column (columnFactor=4)
  2. Wide column (columnFactor=8)
  3. Vertical section column (columnFactor=12)

So Column = 1 maps to the narrow column, not the vertical section. The vertical section controls end up in the wrong column, producing an incorrect page layout.

Steps to reproduce

  1. Create a SharePoint Online team site using the standard Employee onboarding team template — the home page (Employee-onboarding-team-home.aspx) uses a TwoColumnRightVerticalSection layout with controls in the vertical section column
  2. Alternatively, create any modern page with a TwoColumnRightVerticalSection layout and add web parts to the vertical section column (e.g. News, Events, People web parts)
  3. Export the page to a PnP provisioning template using PnP Framework
  4. Inspect the exported template XML — vertical section controls may have Column="1" instead of Column="3" (the vertical column index)
  5. Apply the template to a new site
  6. The vertical section controls appear in the narrow left column instead of the vertical section column

Expected behavior

Controls in the vertical section column should always be exported with a Column value that maps to the vertical section column during import. Since the import creates the vertical section column as the last column, the export should use an index matching that position.

Environment details

  • PnP Framework version: 1.18.x / current dev branch
  • OS: Windows 11
  • Framework: .NET 8.0
  • Tooling: Visual Studio 2022

Additional context

File: src/lib/PnP.Framework/Provisioning/ObjectHandlers/Utilities/ClientSidePageContentsHelper.cs

Original code:

Column = column.IsVerticalSectionColumn ? section.Columns.IndexOf(column) + 1 : column.Order

Fix — use section.Columns.Count for vertical section columns:

Column = column.IsVerticalSectionColumn ? section.Columns.Count : column.Order

This works because:

  • During import, the CanvasSection constructor always creates the vertical section column last (at index Columns.Count - 1)
  • Import looks up columns via page.Sections[sectionCount].Columns[control.Column - 1], so Column = Columns.Count correctly maps to the last column (the vertical section)
  • Columns.Count is stable regardless of HTML parsing order during export

Related PnP Core issue: Section type detection also fails for vertical sections due to the same HTML ordering problem — see the corresponding issue in pnp/pnpcore.

Thanks for your contribution! Sharing is caring.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions