Issue with Document Set content type in custom list templates and CSOM
This post is a contribution from Sohail Sayed, an engineer with the SharePoint Developer Support team
Recently one of the customers encountered an interesting issue with Document Set content types when used in custom list templates and using CSOM to provision the list. Customer had created a list which had multiple content types which were inheriting from Document Set content type. The list was saved as a list template and the list provisioning was being done using JavaScript object model. In this scenario the welcome page for the document set content type was not provisioned correctly and would come up blank. This seems to happen only when provisioning the list using the custom list template via code.
Below is an example
In a working scenario you can see 3 web parts on the welcome page for a Document Set content type as below
It looks like there is an issue due to which the webparts on the welcome page are not provisioned when creating the list from the custom list templates through CSOM. The issue does not happen if we create the list using the custom list template in UI.
Fortunately, there are couple of simple solutions to fix this issue.
The first solution is to remove and re-add the content types of type Document Set in CSOM. This will re-provision the welcome page correctly with the required web parts. However, if the custom list template is saved with content and has list items referencing the Document Set Content types then we will get an error if we try to remove the content types. In this case we can use an alternate solution to add the web parts through code.
The page contains the following 3 web parts
- an Image web part which references a static image from /_layouts folder
- Web part to display document set metadata
- Web Part to display the document set items
All the 3 web parts read the current list item context and we don’t need to explicitly configure any properties like list id or list url.
Below is the sample code for adding the web parts to the welcome page of the document set content types using JSOM.
function fixWebParts(){
var docSetID = "0x0120D5"; // all document sets content types will start with this id
var listName = "DocSet3"; // update list name
var clientContext = SP.ClientContext.get_current();
var oWeb = clientContext.get_web();
var oList = oWeb.get_lists().getByTitle(listName);
var contentTypes = oList.get_contentTypes();
clientContext.load(oList, 'RootFolder');
clientContext.load(contentTypes );
clientContext.executeQueryAsync(onSuccess, onFail);
function onSuccess() {
var rootFolder = oList.get_rootFolder();
var listURL = rootFolder.get_serverRelativeUrl(); // URL of the list
console.log(listURL)
var count = contentTypes.get_count();
for(var i=0; i < count; i++)
{
var id = contentTypes.itemAt(i).get_id().toString();
var name = contentTypes.itemAt(i).get_name();
if (id.startsWith(docSetID)) // this is a document set type
{
AddWebParts(listURL , name );
}
}
}
function onFail(sender, args) {
console.log('Request Failed: ' + args.get_message() + '\n' + args.get_stackTrace());
}
}
function AddWebParts(listRootFolderUrl,contentTypeName){
var pageUrl = listRootFolderUrl + "/forms/" + contentTypeName + "/docsethomepage.aspx";
AddImageWebPart(pageUrl);
AddDocumentSetContentWebPart(pageUrl);
AddDocumentSetPropertiesWebPart(pageUrl);
}
function AddImageWebPart(pageUrl)
{
var webPartXml = '<WebPart xmlns:xsd="https://www.w3.org/2001/XMLSchema" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns="https://schemas.microsoft.com/WebPart/v2">' +
'<Title>Image</Title>' +
'<FrameType>Default</FrameType>' +
'<Description>Use to display pictures and photos.</Description>' +
'<IsIncluded>true</IsIncluded>' +
'<ZoneID>WebPartZone_TopLeft</ZoneID>' +
'<PartOrder>0</PartOrder>' +
'<FrameState>Normal</FrameState>' +
'<Height />' +
'<Width />' +
'<AllowRemove>true</AllowRemove>' +
'<AllowZoneChange>true</AllowZoneChange>' +
'<AllowMinimize>true</AllowMinimize>' +
'<AllowConnect>true</AllowConnect>' +
'<AllowEdit>true</AllowEdit>' +
'<AllowHide>true</AllowHide>' +
'<IsVisible>true</IsVisible>' +
'<DetailLink />' +
'<HelpLink />' +
'<HelpMode>Modeless</HelpMode>' +
'<Dir>Default</Dir>' +
'<PartImageSmall />' +
'<MissingAssembly>Cannot import this Web Part.</MissingAssembly>' +
'<PartImageLarge />' +
'<IsIncludedFilter />' +
'<Assembly>Microsoft.SharePoint, Version=16.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c</Assembly>' +
'<TypeName>Microsoft.SharePoint.WebPartPages.ImageWebPart</TypeName>' +
'<ImageLink xmlns="https://schemas.microsoft.com/WebPart/v2/Image">/_layouts/images/docset_welcomepage_big.png</ImageLink>' +
'<AlternativeText xmlns="https://schemas.microsoft.com/WebPart/v2/Image" />' +
'<VerticalAlignment xmlns="https://schemas.microsoft.com/WebPart/v2/Image">Middle</VerticalAlignment>' +
'<HorizontalAlignment xmlns="https://schemas.microsoft.com/WebPart/v2/Image">Center</HorizontalAlignment>' +
'<BackgroundColor xmlns="https://schemas.microsoft.com/WebPart/v2/Image">transparent</BackgroundColor>' +
'</WebPart>';
AddWebPart(pageUrl,"WebPartZone_TopLeft","0",webPartXml );
}
function AddDocumentSetPropertiesWebPart(pageUrl)
{
var webPartXml = '<WebPart xmlns:xsd="https://www.w3.org/2001/XMLSchema" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns="https://schemas.microsoft.com/WebPart/v2">' +
'<Title>Document Set Properties</Title>' +
'<FrameType>Default</FrameType>' +
'<Description>Displays the properties of the Document Set.</Description>' +
'<IsIncluded>true</IsIncluded>' +
'<ZoneID>WebPartZone_Top</ZoneID>' +
'<PartOrder>0</PartOrder>' +
'<FrameState>Normal</FrameState>' +
'<Height />' +
'<Width />' +
'<AllowRemove>true</AllowRemove>' +
'<AllowZoneChange>true</AllowZoneChange>' +
'<AllowMinimize>true</AllowMinimize>' +
'<AllowConnect>true</AllowConnect>' +
'<AllowEdit>true</AllowEdit>' +
'<AllowHide>true</AllowHide>' +
'<IsVisible>true</IsVisible>' +
'<DetailLink />' +
'<HelpLink />' +
'<HelpMode>Modeless</HelpMode>' +
'<Dir>Default</Dir>' +
'<PartImageSmall />' +
'<MissingAssembly>Cannot import this Web Part.</MissingAssembly>' +
'<PartImageLarge>/_layouts/15/images/msimagel.gif</PartImageLarge>' +
'<IsIncludedFilter />' +
'<DisplayText>' +
'</DisplayText>' +
'<Assembly>Microsoft.Office.DocumentManagement, Version=16.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c</Assembly>' +
'<TypeName>Microsoft.Office.Server.WebControls.DocumentSetPropertiesWebPart</TypeName>' +
'</WebPart>';
AddWebPart(pageUrl,"WebPartZone_Top","0",webPartXml );
}
function AddDocumentSetContentWebPart(pageUrl)
{
var webPartXml = '<WebPart xmlns:xsd="https://www.w3.org/2001/XMLSchema" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns="https://schemas.microsoft.com/WebPart/v2">' +
'<Title>Document Set Contents</Title>' +
'<FrameType>Default</FrameType>' +
'<Description>Displays the contents of the Document Set.</Description>' +
'<IsIncluded>true</IsIncluded>' +
'<ZoneID>WebPartZone_CenterMain</ZoneID>' +
'<PartOrder>0</PartOrder>' +
'<FrameState>Normal</FrameState>' +
'<Height />' +
'<Width />' +
'<AllowRemove>true</AllowRemove>' +
'<AllowZoneChange>true</AllowZoneChange>' +
'<AllowMinimize>true</AllowMinimize>' +
'<AllowConnect>true</AllowConnect>' +
'<AllowEdit>true</AllowEdit>' +
'<AllowHide>true</AllowHide>' +
'<IsVisible>true</IsVisible>' +
'<DetailLink />' +
'<HelpLink />' +
'<HelpMode>Modeless</HelpMode>' +
'<Dir>Default</Dir>' +
'<PartImageSmall />' +
'<MissingAssembly>Cannot import this Web Part.</MissingAssembly>' +
'<PartImageLarge>/_layouts/15/images/msimagel.gif</PartImageLarge>' +
'<IsIncludedFilter />' +
'<DisplayText>' +
'</DisplayText>' +
'<Assembly>Microsoft.Office.DocumentManagement, Version=16.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c</Assembly>' +
'<TypeName>Microsoft.Office.Server.WebControls.DocumentSetContentsWebPart</TypeName>' +
'</WebPart>';
AddWebPart(pageUrl,"WebPartZone_CenterMai","0",webPartXml );
}
function AddWebPart(pageUrl,zoneId,zoneIndex, webPartXml){
var clientContext = SP.ClientContext.get_current();
var oFile = clientContext.get_web().getFileByServerRelativeUrl(pageUrl);
var limitedWebPartManager = oFile.getLimitedWebPartManager(SP.WebParts.PersonalizationScope.shared);
var oWebPartDefinition = limitedWebPartManager.importWebPart(webPartXml);
this.oWebPart = oWebPartDefinition.get_webPart();
limitedWebPartManager.addWebPart(oWebPart,zoneId, zoneIndex);
clientContext.load(oWebPart);
clientContext.executeQueryAsync(Function.createDelegate(this, this.onQuerySucceeded), Function.createDelegate(this, this.onQueryFailed));
}
function onQuerySucceeded()
{
console.log("success");
}
function onQueryFailed(e1,e2,e3)
{
console.log("error");
console.log(e1);
console.log(e2);
console.log(e3);
}