PnP.Core.Provisioning
1.18.42-nightly
dotnet add package PnP.Core.Provisioning --version 1.18.42-nightly
NuGet\Install-Package PnP.Core.Provisioning -Version 1.18.42-nightly
<PackageReference Include="PnP.Core.Provisioning" Version="1.18.42-nightly" />
<PackageVersion Include="PnP.Core.Provisioning" Version="1.18.42-nightly" />
<PackageReference Include="PnP.Core.Provisioning" />
paket add PnP.Core.Provisioning --version 1.18.42-nightly
#r "nuget: PnP.Core.Provisioning, 1.18.42-nightly"
#:package PnP.Core.Provisioning@1.18.42-nightly
#addin nuget:?package=PnP.Core.Provisioning&version=1.18.42-nightly&prerelease
#tool nuget:?package=PnP.Core.Provisioning&version=1.18.42-nightly&prerelease
PnP.Core.Provisioning
The PnP Provisioning Engine on top of the PnP Core SDK.
Describe a SharePoint site as XML — its columns, content types, lists, pages, files, security,
navigation and branding — then extract that description from an existing site and apply it to
another. It is the engine behind PnP provisioning templates and .pnp packages.
⚠️ Experimental
This package is experimental and should be treated as a beta. It is a migration of the PnP Provisioning Engine from PnP Framework — where it is built on CSOM — onto the modern, async, REST and Microsoft Graph based PnP Core SDK.
The API surface may still change, not every handler has equivalent coverage to PnP Framework yet, and you should test a template against a site you can afford to lose before using it in production. Please report what you find — real templates applied to real tenants are the most useful feedback we can get.
Install
dotnet add package PnP.Core.Provisioning
It builds on PnP.Core and PnP.Core.Admin, and is released in lockstep with them — always use
matching versions of all three.
Getting a context
The engine works from a PnPContext, so set up authentication the usual PnP Core way (see the
PnP Core SDK docs). Everything below assumes you have one:
using PnP.Core.Provisioning.Model;
using PnP.Core.Provisioning.Model.Configuration;
using PnP.Core.Provisioning.ObjectHandlers;
using PnP.Core.Provisioning.Providers.Xml;
using (PnPContext context = await pnpContextFactory.CreateAsync("SiteToWorkWith"))
{
IProvisioningManager manager = context.GetProvisioningManager();
}
Extracting a template
By default an extract captures structure only — columns, content types, lists, security, navigation, branding — and none of the content inside them:
IProvisioningManager manager = context.GetProvisioningManager();
ProvisioningTemplate template = await manager.GetTemplateAsync(new ExtractConfiguration
{
ProgressDelegate = (step, current, total) => Console.WriteLine($"{current}/{total} {step}"),
MessagesDelegate = (message, type) => Console.WriteLine($"[{type}] {message}"),
});
Content is opted into per list. Ask for list items, the files in a document library, and the site's pages:
var configuration = new ExtractConfiguration();
configuration.Lists.Lists.Add(new ExtractListsListsConfiguration
{
Title = "Announcements",
IncludeItems = true,
});
configuration.Lists.Lists.Add(new ExtractListsListsConfiguration
{
Title = "Documents",
IncludeFiles = true,
});
configuration.Pages.IncludeAllClientSidePages = true;
// Exported files are written through this connector, so it has to be set when asking for files
configuration.FileConnector = new FileSystemConnector(@"C:\templates", string.Empty);
ProvisioningTemplate template = await manager.GetTemplateAsync(configuration);
Saving a template as XML
using (Stream stream = XMLPnPSchemaFormatter.LatestFormatter.ToFormattedTemplate(template))
using (FileStream file = File.Create(@"C:\templates\marketing.xml"))
{
stream.CopyTo(file);
}
Saving a template as a .pnp package
A .pnp package is a single file holding the template and everything it references — the XML
plus the files exported from libraries. Prefer it whenever the template ships content, because an
.xml template leaves those files beside it on disk and they are easy to lose:
var package = new OpenXMLConnector(
"marketing.pnp",
new FileSystemConnector(@"C:\templates", string.Empty),
author: "Contoso",
signingCertificate: null,
templateFileName: "template.xml");
// Point the extract at the package so exported files are written into it
configuration.FileConnector = package;
ProvisioningTemplate template = await manager.GetTemplateAsync(configuration);
new XMLOpenXMLTemplateProvider(package).SaveAs(template, "template.xml");
Applying a template
From XML
ProvisioningTemplate template;
using (Stream stream = File.OpenRead(@"C:\templates\marketing.xml"))
{
template = XMLPnPSchemaFormatter.LatestFormatter.ToProvisioningTemplate(stream);
}
// The connector is how the template reaches the files next to it. Without it a template that
// carries files applies and quietly brings none of them.
template.Connector = new FileSystemConnector(@"C:\templates", string.Empty);
await context.GetProvisioningManager().ApplyTemplateAsync(template, new ApplyConfiguration
{
ProgressDelegate = (step, current, total) => Console.WriteLine($"{current}/{total} {step}"),
MessagesDelegate = (message, type) => Console.WriteLine($"[{type}] {message}"),
});
From a .pnp package
var package = new OpenXMLConnector(
"marketing.pnp",
new FileSystemConnector(@"C:\templates", string.Empty));
ProvisioningTemplate template = new XMLOpenXMLTemplateProvider(package).GetTemplate("template.xml");
template.Connector = package;
await context.GetProvisioningManager().ApplyTemplateAsync(template);
Reading what the engine reports
MessagesDelegate is worth wiring up. The engine reports a problem and carries on rather than
stopping at the first one, so a run can finish having quietly skipped part of the template — a
sealed content type it may not update, an artefact a NoScript site refuses, a webhook that cannot
be re-registered. "It finished" and "it all worked" are different claims, and the messages are how
you tell them apart.
Tenant templates (hierarchies)
A template can also describe the site collections to create, in a sequence. Applying one creates the sites and then applies the templates attached to them:
ProvisioningHierarchy hierarchy = new XMLOpenXMLTemplateProvider(package).GetHierarchy();
await context.GetProvisioningManager().ApplyTenantTemplateAsync(
hierarchy,
hierarchy.Sequences.First().ID,
new ApplyConfiguration
{
Parameters =
{
["SiteTitle"] = "Marketing",
["SiteUrl"] = "/sites/marketing",
},
});
Two things to know about hierarchies:
- Site urls in a template may be relative (
/sites/marketing); they are resolved against the tenant of the context you apply with. - A site collection in a hierarchy needs an explicit
Ownerwhen you authenticate as an application. With a signed-in user the owner defaults to that user; app-only has no current user to fall back on.
A working sample
Demo.Console.Provisioning
is a console app built on this package. It extracts templates (with or without content), saves them
as .xml or .pnp, shows what a template contains, applies one to an existing site or to a new
communication site it creates for you, and covers both interactive and app-only authentication.
It is the quickest way to see the engine work end to end.
Feedback
Issues and pull requests are welcome at github.com/pnp/pnpcore. Given this package's experimental status, reports of templates that fail to extract or apply are especially valuable — please include the messages the engine reported.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- PnP.Core (>= 1.18.42-nightly)
- PnP.Core.Admin (>= 1.18.42-nightly)
- Portable.Xaml (>= 0.26.0)
- System.IO.Packaging (>= 4.7.0)
-
net10.0
- PnP.Core (>= 1.18.42-nightly)
- PnP.Core.Admin (>= 1.18.42-nightly)
- Portable.Xaml (>= 0.26.0)
- System.IO.Packaging (>= 10.0.0)
-
net8.0
- PnP.Core (>= 1.18.42-nightly)
- PnP.Core.Admin (>= 1.18.42-nightly)
- Portable.Xaml (>= 0.26.0)
- System.IO.Packaging (>= 8.0.1)
-
net9.0
- PnP.Core (>= 1.18.42-nightly)
- PnP.Core.Admin (>= 1.18.42-nightly)
- Portable.Xaml (>= 0.26.0)
- System.IO.Packaging (>= 9.0.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.18.42-nightly | 0 | 9/28/2026 |
| 1.18.41-nightly | 30 | 9/27/2026 |
| 1.18.40-nightly | 36 | 9/26/2026 |
| 1.18.39-nightly | 40 | 9/25/2026 |
| 1.18.38-nightly | 47 | 9/24/2026 |
| 1.18.37-nightly | 50 | 9/23/2026 |
| 1.18.36-nightly | 54 | 9/23/2026 |
| 1.18.35-nightly | 50 | 9/22/2026 |
| 1.18.34-nightly | 64 | 9/21/2026 |
| 1.18.33-nightly | 56 | 9/20/2026 |