Tag Archives: site provisioning

PnP Provisioning

Extract and apply templates with Office Dev PnP Provisioning PowerShell

Earlier I introduced the Office Dev PnP Program and Office Dev PnP Provisioning. I mentioned the great functionality to define a template of a site or site collection in XML. In this blog post I will explain how to extract and apply XML templates with Office Dev PnP Provisioning using the Office 365 Developer Patterns and Practices PowerShell Cmdlets, from now on referred to as PnP Provisioning cmdlets.

PnP Provisioning cmdlets?

Basically the PnP Provisioning cmdlets are an extension to the standard CSOM functionality Microsoft offers. PnP Provisioning cmdlets are specifically designed to provision and modify artifacts in SharePoint Online using CSOM.

Layers of CSOM and PnP

Preparing you environment

Of course, you first need to prepare your environment before you are able to use the PnP Provisioning cmdlets. Although the cmdlets are designed for SharePoint Online, it is also possible to use the cmdlets on an on-premises environment. The on-premises variant of the cmdlets is another build, because SharePoint 2013 uses an older version (15) of CSOM whereas SharePoint Online uses the newest version (16) of CSOM. Therefore you first need to determine the right build of the PnP Provisioning cmdlets:

  • msi for SharePoint 2013
  • msi for SharePoint Online

Next download the latest release of the right build from the release page and run the install. Erwin van Hunen created a blog post about running the install and connecting to the SharePoint environment with Connect-SPOnline. Complete the installation as described in his blog post.

Connect and get the context

As mentioned earlier you can use Connect-SPOnline to connect to SharePoint. Connect-SPOnline creates the context you need to acquire or apply the XML template.

To ease your life, use the Windows Credential Manager to store your credentials. This way you don’t have to fill in your credentials each time you connect to SharePoint with Connect-SPOnline without having to hardcode your credentials in the script.

Almost ready to extract

Once you have the necessary context you are almost ready to extract a template. One thing is missing: the source to extract from. The source is a SharePoint site which is designed as the blueprint of to be provisioned sites. Create this source site exactly as you want this blueprint to be. Do this in a root site (of a separate site collection) for best results. In a subsite it is possible that some artifacts are not extracted properly. Things like site columns are only obtained correctly when the source is a root site. Once you created the source site, you are ready to extract.

Extract a XML template with Get-SPOProvisioningTemplate

Now you have a source site as blueprint, you need the context of the source site. So if /sites/MySourceSite is the source site your code should look like something like this:

# Define variables
$tenant = "tenantName";
$sourceSite = "/sites/MySourceSite";
$path = "C:\MyPnPTemplate.xml";

# Get context
$webUrl = "https://{0}.sharepoint.com{1}/" -f $tenant, $sourceSite;
Write-Output $("Connecting to {0}..." -f $webUrl);
Connect-SPOnline -Url $webUrl -Credentials WCMStoredCredentials;
Write-Output "Context obtained";

To make the script easier to use with different environments, I used a $tenant and a $sourceSite variable to define the name of the SharePoint tenant and the source site respectively. Later these variables are used in $webUrl to define the complete URL of the source site. The $path variable is to define the location where the XML template should be saved. Last thing to do is the actual extraction with Get-SPOProvisioningTemplate and save the XML template to the given path:

# Extract template
Write-Output "Creating PnP template...";
Get-SPOProvisioningTemplate -Out $path;
Write-Output $("Template saved to {0}" –f $path);
Combined the code looks like this:

# Define variables
$tenant = "tenantName";
$sourceSite = "/sites/MySourceSite";
$path = "C:\MyPnPTemplate.xml";

# Get context
$webUrl = "https://{0}.sharepoint.com{1}/" -f $tenant, $sourceSite;
Write-Output $("Connecting to {0}..." -f $webUrl);
Connect-SPOnline -Url $webUrl -Credentials WCMStoredCredentials;
Write-Output "Context obtained";

# Extract template
Write-Output "Creating PnP template...";
Get-SPOProvisioningTemplate -Out $path;
Write-Output $("Template saved to {0}" –f $path);

Apply a XML template with Apply-SPOProvisioningTemplate

Applying a XML template is as easy as extracting a XML template. Obtaining the context works the same, but instead of a defining source site, you define a target site. With Get-SPOWeb you get the context of the subsite. Now it’s time to apply the XML template with Apply-SPOProvisioningTemplate:

# Define variables
$tenant = "tenantName";
$targetSite = "/sites/MyTargetSite";
$path = "C:\MyPnPTemplate.xml";

# Get context
$webUrl = "https://{0}.sharepoint.com{1}" -f $tenant, $ targetSite;
Write-Output $("Connecting to {0}..." -f $webUrl);
Connect-SPOnline -Url $webUrl -Credentials WCMStoredCredentials;
Write-Output "Context obtained";

# Get web object
$web = Get-Web;

# Apply template
Write-Output $("Applying PnP template [{0}] to site [{1} ({2})]..." -f $path, $web.Title, $web.Url);
Apply-SPOProvisioningTemplate -Web $web -Path $path;
Write-Output "Template created";

After some time (seconds or minutes, depending on the size of the template and the connection speed) your template will be successfully applied to the site.

In the sample a $web context is used as input for Apply-SPOProvisioningTemplate, but when no web context is given, Apply-SPOProvisioningTemplate will use the context of Connect-SPOnline (which in this sample is indeed the same context as $web). The code will then look like:

Apply-SPOProvisioningTemplate -Path $path;

The XML template is now applied on an existing site. It could also be applied to a new site by creating the new site first with New-SPOWeb using the standard blank (STS#1) template.

# Define variables
$tenant = "tenantName";
$targetSite = "/sites/MyTargetSite";
$path = "C:\MyPnPTemplate.xml";
$siteTitle = "My Target Site";
$siteDescription = "My Target Site Description";
$siteUrl = "MyTargetSite";

# Get context
$webUrl = "https://{0}.sharepoint.com/{1}" -f $tenant, $targetSite;
Write-Output $("Connecting to {0}..." -f $webUrl);
Connect-SPOnline -Url $webUrl -Credentials WCMStoredCredentials;
Write-Output "Done";

# Create new subsite
$web = New-SPOWeb -Title "$siteTitle" -Url "$siteUrl" -Description "$siteDescription" -Locale 1043 -Template "STS#1"

# Apply template
Write-Output $("Applying PnP template [{0}] to site [{1} ({2})]..." -f $path, $web.Title, $web.Url);
Apply-SPOProvisioningTemplate -Web $web -Path $path;
Write-Output "Done";

This is also a good example of a situation when you actually need the $web context. In the coming blog posts I will explain how to create a XML template yourself.

Further information

PnP Provisioning

Getting started with Office Dev PnP Provisioning

Office Dev PnP provides a site provisioning engine to create sites and site collections within a SharePoint Online tenant or a SharePoint farm based on a given definition. This definition is an object describing the to be provisioned components like list, libraries and features. But also SharePoint security groups, users, site property bags entries and Composed Looks.

With the template provider the definition object can be transformed to JSON or XML. This works in both ways, so you can transform a XML definition into an object. Therefore you are able to define the structure of a site or site collection in a XML template. The definition object will be referred to as PnP template.

Classic site provisioning techniques

Below are a few classic site provisioning techniques. Vesa Juvonen explains these techniques in more detail.

Site Definition
Requires full trust solutions, which means it is not possible to use in Office 365. Also it will be difficult to migrate site definitions to newer versions of SharePoint.

Site Templates
Not possible to create site collections without workarounds and is difficult to upgrade. This method is however possible on Office 365.

Web Templates
Not possible to create site collections without workarounds. This method is however possible on Office 365.

Server side provisioning
Provides standardization of site creation in code and is easy to upgrade. Requires full trust solutions, which means it is not possible to use in Office 365.

Introducing remote provisioning and PnP Provisioning

The modern way of site provisioning is remote provisioning. Remote provisioning uses the Client Side Object Model (CSOM) or the REST API to create a site and fill this site incrementally with CSOM/REST requests. This model is suitable for both on-premises and Office 365 since we control the customizations outside of the SharePoint farm in an independent solution.

To improve the experience using remote provisioning, the Office Dev PnP team created PnP Provisioning. As mentioned earlier, a really great part of PnP Provisioning is defining a site template in a XML using the PnP Provisioning Schema. In my next blog post I will explain how to create a site based on a template defined using the PnP Provisioning Schema.

Further information