Skip to content

Commit

Permalink
Loading site pages is more robust when a custom web part on the page …
Browse files Browse the repository at this point in the history
…is erroring #1410
  • Loading branch information
jansenbe committed Mar 13, 2024
1 parent c3c30ca commit 2f37489
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 15 deletions.
1 change: 1 addition & 0 deletions src/sdk/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/).

- Calls to `GetUserEffectivePermissions` are not not clearing collections loaded in the used `PnPContext` instance #1416 [jansenbe - Bert Jansen]
- Verify TermId is a valid GUID before assigning it #1414 [jansenbe - Bert Jansen]
- Loading site pages is more robust when a custom web part on the page is erroring #1410 [jansenbe - Bert Jansen]

## [1.12.0]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,7 @@ internal static Type GetType(string controlDataJson)
#endregion

#region Internal and private methods
internal virtual void FromHtml(IElement element)
internal virtual void FromHtml(IElement element, bool isHeader)
{
var controlData = JsonSerializer.Deserialize<CanvasControlData>(element.GetAttribute(ControlDataAttribute), PnPConstants.JsonSerializer_IgnoreNullValues);

Expand Down
8 changes: 4 additions & 4 deletions src/sdk/PnP.Core/Model/SharePoint/Pages/Internal/Page.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1171,7 +1171,7 @@ private void LoadFromHtml(string html, string pageHeaderHtml)
{
if (string.IsNullOrEmpty(html))
{
throw new ArgumentNullException(nameof(pageHeaderHtml));
throw new ArgumentNullException(nameof(html));
}

HtmlParser parser = new HtmlParser(new HtmlParserOptions() { IsEmbedded = true });
Expand All @@ -1195,7 +1195,7 @@ private void LoadFromHtml(string html, string pageHeaderHtml)
{
Order = controlOrder
};
control.FromHtml(clientSideControl);
control.FromHtml(clientSideControl, false);

// Handle control positioning in sections and columns
ApplySectionAndColumn(control, control.SpControlData.Position, control.SpControlData.Emphasis, control.SpControlData.ZoneGroupMetadata);
Expand All @@ -1208,7 +1208,7 @@ private void LoadFromHtml(string html, string pageHeaderHtml)
{
Order = controlOrder
};
control.FromHtml(clientSideControl);
control.FromHtml(clientSideControl, false);

// Handle control positioning in sections and columns
ApplySectionAndColumn(control, control.SpControlData.Position, control.SpControlData.Emphasis, control.SpControlData.ZoneGroupMetadata);
Expand Down Expand Up @@ -1455,7 +1455,7 @@ private void LoadFromHtml(string html, string pageHeaderHtml)
Order = headerControlOrder,
IsHeaderControl = true,
};
control.FromHtml(clientSideHeaderControl);
control.FromHtml(clientSideHeaderControl, true);

HeaderControls.Add(control);
headerControlOrder++;
Expand Down
4 changes: 2 additions & 2 deletions src/sdk/PnP.Core/Model/SharePoint/Pages/Internal/PageText.cs
Original file line number Diff line number Diff line change
Expand Up @@ -168,9 +168,9 @@ public override string ToHtml(float controlIndex)
#endregion

#region Internal and private methods
internal override void FromHtml(IElement element)
internal override void FromHtml(IElement element, bool isHeader)
{
base.FromHtml(element);
base.FromHtml(element, isHeader);

var div = element.GetElementsByTagName("div").FirstOrDefault(a => a.HasAttribute(TextRteAttribute));

Expand Down
43 changes: 35 additions & 8 deletions src/sdk/PnP.Core/Model/SharePoint/Pages/Internal/PageWebPart.cs
Original file line number Diff line number Diff line change
Expand Up @@ -515,9 +515,9 @@ internal void RenderHtmlProperties(ref StringBuilder htmlWriter)
#endregion

#region Internal and private methods
internal override void FromHtml(IElement element)
internal override void FromHtml(IElement element, bool isHeader)
{
base.FromHtml(element);
base.FromHtml(element, isHeader);

// Set/update dataVersion if it was provided as html attribute
var webPartDataVersion = element.GetAttribute(WebPartDataVersionAttribute);
Expand All @@ -530,22 +530,49 @@ internal override void FromHtml(IElement element)
controlType = SpControlData.ControlType;
RichTextEditorInstanceId = SpControlData.RteInstanceId;

var wpDiv = element.GetElementsByTagName("div").FirstOrDefault(a => a.HasAttribute(WebPartDataAttribute));
IElement wpDiv = null;
string decodedWebPart = null;

string decodedWebPart;
// Some components are in the page header and need to be handled as a control instead of a webpart
if (wpDiv == null)
if (isHeader)
{
// Decode the html encoded string
decodedWebPart = WebUtility.HtmlDecode(element.GetAttribute(ControlDataAttribute));
IsHeaderControl = true;
}
else
{
WebPartData = wpDiv.GetAttribute(WebPartAttribute);
wpDiv = element.GetElementsByTagName("div").FirstOrDefault(a => a.HasAttribute(WebPartDataAttribute));
if (wpDiv != null)
{
// This is a valid web part
WebPartData = wpDiv.GetAttribute(WebPartAttribute);

// Decode the html encoded string
decodedWebPart = WebUtility.HtmlDecode(wpDiv.GetAttribute(WebPartDataAttribute));
// Decode the html encoded string
decodedWebPart = WebUtility.HtmlDecode(wpDiv.GetAttribute(WebPartDataAttribute));
}
else
{
// The web part is not presented by a data-sp-webpartdata attribute on the DIV, typically
// this means the web part is broken. Check the page and see if it renders properly

// Let's try to get the web part data from the webPartData element in the control data attribute json content
var controlDataAttributeJsonContent = WebUtility.HtmlDecode(element.GetAttribute(ControlDataAttribute));
if (!string.IsNullOrEmpty(controlDataAttributeJsonContent))
{
var controlDataAttributeJsonObject = JsonSerializer.Deserialize<JsonElement>(controlDataAttributeJsonContent);
if (controlDataAttributeJsonObject.TryGetProperty("webPartData", out JsonElement webPartDataProperty) && webPartDataProperty.ValueKind != JsonValueKind.Null)
{
decodedWebPart = webPartDataProperty.ToString();
}
}
}
}

// If above fallback code did not result in web part data then return with just the basic info we have
if (string.IsNullOrEmpty(decodedWebPart))
{
return;
}

var wpJObject = JsonSerializer.Deserialize<JsonElement>(decodedWebPart);
Expand Down

0 comments on commit 2f37489

Please sign in to comment.