This is a quick 'how-to' for setting items in the Quick Links web part on a modern SharePoint page - for example when provisioning team sites or upgrading existing sites to use the modern experience and migrating content from Promoted Links to Quick Links.
If you want to create Quick Link items from code, you'll need to understand the format of data that SharePoint is expecting when updating the web part properties. The easiest way to achieve this is add a Quick Links web part to the SharePoint workbench page (https://yourtenant.sharepoint.com/_layouts/15/workbench.aspx) and then click the Web part data button at the top of the page to see how that data is serialised in a modern page.
To set Quick Links items, first create a QuickLinkItem entity class and some other related classes:
public class QuickLinkItem
{
public string UniqueId { get; set; }
public string Url { get; set; }
public string Title { get; set; }
public QuickLinkRenderInfo RenderInfo { get; set; }
}
public class QuickLinkRenderInfo
{
public string imageUrl { get; set; }
public QuickLinkCompactImageInfo compactImageInfo { get; set; }
public string backupImageurl { get; set; }
public string iconUrl { get; set; }
public string accentColor { get; set;}
public int imageFit { get; set; }
public bool forceStandardImageSize { get; set; }
public static QuickLinkRenderInfo DocLibrary = new QuickLinkRenderInfo
(
"https://spoprod-a.akamaihd.net/files/sp-client-prod_2017-09-29.016/icon_doc-library_04a9a5ce.png",
"https://spoprod-a.akamaihd.net/files/sp-client-prod_2017-09-29.016/icon_genericfile_56b72b7b.png",
"DocLibrary"
);
public static QuickLinkRenderInfo Globe = new QuickLinkRenderInfo
(
"https://spoprod-a.akamaihd.net/files/sp-client-prod_2017-09-29.016/icon_link_22d1503c.png",
"https://spoprod-a.akamaihd.net/files/sp-client-prod_2017-09-29.016/icon_genericfile_56b72b7b.png",
"Globe"
);
public QuickLinkRenderInfo(string imageUrl, string iconUrl, string iconName)
{
this.imageUrl = imageUrl;
compactImageInfo = new QuickLinkCompactImageInfo
{
iconName = iconName,
color = string.Empty,
imageUrl = imageUrl,
forceIconSize = true
};
backupImageurl = string.Empty;
this.iconUrl = iconUrl;
accentColor = string.Empty;
imageFit = 0;
forceStandardImageSize = true;
isFetching = false;
}
}
public class QuickLinkCompactImageInfo
{
public string iconName { get; set; }
public string color { get; set; }
public string imageUrl { get; set; }
public bool forceIconSize { get; set; }
}
You'll also need some methods for updating the Quick Links web part data using your QuickLinkItem instances:
// converts a QuickLinkItem into the JSON format expected by SharePoint
private JObject GetQuickLinkItem(int quickLinkItemId, string siteUrl, string siteId, string webId, QuickLinkItem quickLinkItem)
{
var siteUri = new Uri(siteUrl);
bool external = quickLinkItem.Url[0] != '/' && !quickLinkItem.Url.StartsWith($"https://{siteUri.Host}", StringComparison.CurrentCultureIgnoreCase);
string blankGuid = new Guid().ToString();
JObject item = JObject.FromObject(new
{
id = quickLinkItemId,
itemType = external ? 2 : 5,
siteId = external ? blankGuid : siteId,
webId = external ? blankGuid : webId,
uniqueId = quickLinkItem.UniqueId,
fileExtension = quickLinkItem.Url,
progId = "",
activity = new
{
activity = "Added a few seconds ago",
people = new object[]
{
new
{
name = "SharePoint",
profileImageSrc = "https://spoprod-a.akamaihd.net/files/sp-client-prod_2017-09-29.011/icon_sp-icon_fd9ed950.png",
initials = ""
}
}
},
hasInvalidUrl = !external,
flags = 0,
renderInfo = quickLinkItem.RenderInfo
});
return item;
}
// generates the ServerProcessedContent data required to ensure that the OfficeDev PnP code generates the necessary HTML property elements
private JObject GetQuickLinksServerProcessedContent(string webUrl, string siteId, string webId, List<QuickLinkItem> quickLinkItems)
{
JObject searchablePlainTexts = new JObject();
JObject imageSources = new JObject();
JObject links = new JObject();
for (var index = 0; index < quickLinkItems.Count; index++)
{
var quickLink = quickLinkItems[index];
var renderInfoLinkUrl = GetRenderInfoLinkUrl(webUrl, siteId, webId, quickLink.UniqueId);
searchablePlainTexts.Add($"items[{index}].title", quickLink.Title);
searchablePlainTexts.Add($"items[{index}].caption", string.Empty);
imageSources.Add($"items[{index}].pictureUrl", string.Empty);
links.Add($"items[{index}].url", quickLink.Url);
links.Add($"items[{index}].renderInfo.linkUrl", renderInfoLinkUrl);
}
JObject serverProcessedContent = JObject.FromObject(new
{
htmlStrings = new JObject(),
searchablePlainTexts = searchablePlainTexts,
imageSources = imageSources,
links = links
});
return serverProcessedContent;
}
private string GetRenderInfoLinkUrl(string webUrl, string siteId, string webId, string uniqueId)
{
return $"{webUrl}/_layouts/15/ShortcutLink.aspx?siteId={siteId}&webId={webId}&uniqueId={uniqueId}&web=1";
}
// creates and populates a Quick Links web part
private ClientSideWebPart CreateQuickLinksWebPart(ClientContext clientContext, ClientSidePage page, List<QuickLinkItem> quickLinks)
{
clientContext.Load(clientContext.Site, s => s.Id);
clientContext.Load(clientContext.Web, w => w.Id, w => w.Url);
clientContext.Load(page.PageListItem, p => p.Id);
clientContext.ExecuteQueryRetry();
string siteId = clientContext.Site.Id.ToString();
string webId = clientContext.Web.Id.ToString();
JObject serverProcessedContent = GetQuickLinksServerProcessedContent(clientContext.Web.Url, siteId, webId, quickLinks);
var quickLinksWebPart = page.InstantiateDefaultWebPart(DefaultClientSideWebParts.QuickLinks);
quickLinksWebPart.PropertiesJson = JObject.FromObject(new
{
controlType = 3,
displayMode = 2,
id = "05924478-460a-417a-afa8-83792656eff7",
position = new
{
zoneIndex = 1,
sectionIndex = 1,
controlIndex = 1
},
webPartId = quickLinksWebPart.WebPartId,
webPartData = new
{
id = quickLinksWebPart.WebPartId,
instanceId = Guid.NewGuid().ToString(),
title = "Quick links",
description = "Add links to important documents and pages.",
serverProcessedContent = serverProcessedContent,
dataVersion = "1.0",
properties = new
{
items = quickLinks.Select((QuickLinkItem quickLink, int index) => GetQuickLinkItem(index + 1, clientContext.Web.Url, siteId, webId, quickLink)),
isMigrated = true,
layoutId = "FilmStrip",
shouldShowThumbnail = true,
hideWebPartWhenEmpty = true,
dataProviderId = "QuickLinks",
webId = webId,
siteId = siteId,
baseUrl = clientContext.Web.Url
}
}
}).ToString();
return quickLinksWebPart;
}
To use these classes and methods to add a quick links web part including some links to an existing page:
string pageName = "Test page.aspx";
ClientSidePage page = ClientContext.Web.LoadClientSidePage(pageName);
// quick link entities
List<QuickLinkItem> quickLinkItems = new List<QuickLinkItem>
{
// internal link
new QuickLinkItem
{
UniqueId = Guid.NewGuid().ToString(),
Url = "/sites/testSite/SitePages",
Title = "Site Pages",
RenderInfo = QuickLinkRenderInfo.DocLibrary
},
// external link
new QuickLinkItem
{
UniqueId = Guid.NewGuid().ToString(),
Url = "https://www.bing.com/search?q=Google+Chrome",
Title = "Google Chrome",
RenderInfo = QuickLinkRenderInfo.Globe
}
};
ClientSideWebPart quickLinksWebPart = CreateQuickLinksWebPart(clientContext, page, quickLinkItems);
page.AddControl(quickLinksWebPart);
page.Save();
Thanks for publishing this - I was looking for this kind of information
I have successfully used it to add quick links with layoutId = "FilmStrip"
When I try to use it with layoutId = "CompactCard" I am not able to make the link icon appear (apart from that it works)
Do you have a working sample with layoutId = "CompactCard"?