PnP PowerShell and more...

Here I occasionally post about Microsoft 365 Patterns and Practices in general and PnP PowerShell more specifically.

Using an extensibility provider with the PnP Provisioning Engine

2015-08-25 2 min read PowerShell SharePoint Provisioning Engine

When you use the provisioning engine of the PnP Core project, you can provide an extensibility provider in your XML file. In order to use the Apply-SPOProvisioningTemplate cmdlet with an XML file that contains such a reference, it is important that you also load the assembly, otherwise the engine will fail to instantiate your provider and as a result, the provider will not be executed.

An extensibility provider is nothing but a simple class:

namespace MyCompany.ExtensibilityProviders 
{
  public class MainProvider : IProvisioningExtensibilityProvider
  {
    public void ProcessRequest(ClientContext ctx, ProvisioningTemplate template, string configurationData)
    {
      // do something in your provider            
    }
  }
}

In the ProcessRequest method we can basically do anything we want. We receive a ClientContext object, we get a handle to the provisioning template object, and we are sent any optional configuration data. These providers are the ideal way to extend the engine with functionality that is not built-in currently.

We then configure the provider in our provisioning template, by adding the following snippet:

<pnp:Providers>
  <pnp:Provider Enabled="true" HandlerType="MyCompany.ExtensibilityProviders.MainProvider, MyCompany.ExtensibilityProviders, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
    <pnp:Configuration>
      <MyProviderConfiguration id="SampleConfig" xmlns="http://schemas.somecompany.com/MyProviderConfiguration">
        <ChildNode Attribute="value">TextContent</ChildNode>
      </MyProviderConfiguration>
    </pnp:Configuration>
  </pnp:Provider>
</pnp:Providers>

The MainProvider class will then be called when the engine is done provisioning the template to the site. In ‘old-school’ SharePoint terminology, think of it as an event receiver.

According to the XML snippet above, the provider is located in an assembly called MyCompany.ExtensibilityProviders.dll. In there is a class, called MainProvider. In order for the provisioning engine to be able to find this assembly you could (but I don’t recommend it) add the assembly to the Global Assembly Cache. Lots of hassle. Not worth it.

Instead, we can load the assembly in your current PowerShell session instead. That way the engine will be able to create an instance of the MainProvider class and execute the code accordingly. See the following PowerShell snippet:

Connect-SPOnline -Url https://yoursite.sharepoint.com
Add-Type -Path MyCompany.ExtensibilityProviders.dll
Apply-SPOProvisioningTemplate -Path <pathtoyourtemplate.xml>

Notice that I execute Add-Type after Connect-SPOnline. This is because your provider assembly is depending on OfficeDevPnP.Core.dll, which is an assembly that is loaded by Connect-SPOnline. If you execute the Add-Type cmdlet before the Connect-SPOnline cmdlet, you will likely receive an error message otherwise.