Welcome to Part 2 of this series on Automated SharePoint Site Provisioning with PnP.  This blog series is focused on lessons learned with using PnP Powershell along with Site Actions, Site Scripts, Azure Automation and other components in order to automate creation of new SharePoint sites in a repeatable and well-governed manner. 

If you haven’t reviewed part 1, you can check it out here:

Tl;DR; when using Document Sets in your PnP Provisioning solution, be sure to:

  1. Enable site scripting (by setting DenyAddAndCustomizePages to false)
  2. Include feature activation for Document Sets in your provisioning template

This article shall is focused on something I just came across tonight, and figured I would post it while its fresh in my head.  The situation I stumbled on was related to deploying Document Sets as part of a provisioning site template.  In this case, I had a base PnP provisioning template with existing sections for SiteFields and ContentTypes containing a few basic site columns and content types. 

But now I added a custom document set content type (named “Project Packet”) to my test site which included columns for values like Project Manager, Project Name, Status, Start Date & End Date.  Since I needed to replicate the functionality of my test site in a new site, I added the related elements for my new SiteFields and ContentTypes to my existing provisioning template.

Using the “Features” handler in PnP

When you want to use Document Sets in a new site, you have to activate the Document Sets Site Collection feature (until you do this the base Document Set content type is not deployed into the site).  Rather than doing this through the normal Site Settings, I decided to update my provisioning template to handle this for me.  Since this was my first time using PnP Provisioning with Document Sets, I ran the following Powershell cmdlet on my test site which already had the Document Set feature activated:

Get-PnPProvisioningTemplate out “MyTemplate-Features.xml”
                            –Handlers “Features”

Note the use of the –Handlers parameter with a value of “Features”.  This tells the cmdlet to only export the custom site (site collection) and web features from the site, so we’ll get a small template from this, such as shown below:

<?xml version=“1.0”?>
     Generator=“OfficeDevPnP.Core, Version=3.2.1810.0,
                 Culture=neutral, PublicKeyToken=5e633289e95c321a” />
  <pnp:Templates ID=“CONTAINER-TEMPLATE-D9976DB23F1040BAB0A41BE5BC677F83”>
   <pnp:ProvisioningTemplate ID=“TEMPLATE-D9976DB23F1040BAB0A41BE5BC677F83”
                              Version=“1” BaseSiteTemplate=“GROUP#0”
      <pnp:Feature ID=“3bae86a2-776d-499d-9db8-fa4cdc7884f8” />
      <pnp:Feature ID=“f151bb39-7c3b-414f-bb36-6bf18872052f” />

In this case, the Site Feature of “3bae86a2-776d-499d-9db8-fa4cdc7884f8” is the Document Set feature.  The Web Feature of “f151bb39-7c3b-414f-bb36-6bf18872052f” refers to the Site Notebook feature.  Quick side note: It’s a mystery to me why the Site Notebook feature was included here.  I did not explicitly activate the Site Notebook feature as it is activated by default in modern team sites.  If I run the same powershell cmdlets on a brand new modern team site that does not have the Document Set feature activated, the generated PnP template does not contain either of these features.  But for some reason, the PnP engine feels that it needs to include the Site Notebook feature along with the Document Set feature.

I now copied the <pnp:Features> </pnp:Features> section from this Xml file and merged into my main pnp template (above the section for <pnp:SiteFields>).  At this point I now have two PnP provisioning templates:

  1. FieldCTs.xml – with sections for Features, SiteFields and ContentTypes (as described above)
  2. Lists.xml – with list definitions containing references to my Project Packet content type and related columns

Now, I figured, I’m good to go and I applied my updated pnp template containing the Document Set feature activation along with my custom document set content type (Project Packet) and associated columns, using these PowerShell cmdlets:

ApplyPnPProvisioningTemplate –Path “FieldCTs.xml”
ApplyPnPProvisioningTemplate –Path “Lists.xml”

These cmdlets completed without error.  So I went in to use my updated site.  From the library containing my Project Packet content type I clicked on new Project Packet and filled out the metadata fields and clicked Ok. But instead of seeing my new Project Packet document set, I was greeted with a 404 error!  I tested this a few times and replicated the error on additional sites.

Enable Site Scripting

So with a little research, I found that in order to activate the Document Set feature properly, we first need to enable site scripting on the target site.  This article in the PnP-Sites-Core github repo got me started down the right path, but it referenced a solution using SharePoint Online powershell. I wanted to complete this using PnP powershell.  I also found this discussion from the MS Tech Community to be helpful: How do I set DenyAddAndCustomizePages using PnP? (thanks Alan Trafford and Pieter Veenstra).

So here is the final script with everything together:

Import-module SharePointPnPPowerShellOnline
Set-PnPTraceLog On LogFile “pnplog.txt” Level Debug
$DenyAddCustomizeEnum =
Connect-PnPOnlineUrl https://tenant-admin.sharepoint.com
$ctx = Get-PnPContext
$site = Get-PnPTenantSite Detailed Url $siteUrl
Write-Host “Site: $site
$site.DenyAddAndCustomizePages = $DenyAddCustomizeEnum::Disabled
Write-Host “Disabled DenyAddAndCustomizePages”
Get-PnPTenantSite Detailed Url $siteUrl |
Select-Object url,DenyAddAndCustomizePages
$status = $null
Write-Host “Waiting… $status
Start-Sleep Seconds 5
$Site=Get-PnPTenantSite url $siteUrl Detailed
$status = $Site.Status
} While ($status -ne ‘Active’)
ApplyPnPProvisioningTemplate –Path “FieldCTs.xml”
ApplyPnPProvisioningTemplate –Path “Lists.xml”
Write-Error “Exception Occured”
Write-Error “Exception Type: $($_.Exception.GetType().FullName)”
Write-Error “Exception Message: $($_.Exception.Message)”
Set-PnPTraceLog – –off


So when including document sets within your PnP Provisioning solution, remember two things:

  1. Enable site scripting (by setting DenyAddAndCustomizePages to false)
  2. Include feature activation in your provisioning template

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s