预配控制台应用程序示例
为了支持新的外接程序模型,Office 365 开发人员模式和做法 (PnP) 计划引入了预配框架,允许用户:
- 只需指向网站模型即可创建自定义网站模板。
- 保留模型作为预配模板。
- 根据需要将自定义模板应用到现有网站集。
在此示例中,我们将创建基本控制台应用程序,在设置 PnP 核心库的过程中实现类,从而使 PnP 设置引擎能够完成以下基本设置任务:
- 设计并构建网站自定义模型。 可以设计新的网站,也可以指向现有网站并将其另存为设置模板。
- 保存并将网站模型保留为设置模板,以便您可以重复使用它。
- 将预配模板应用到新网站集或现有网站集。
注意
此示例演练是 GitHub 上现有示例 PnP 预配引擎入门的配套示例。 此示例的代码 (Program.cs) 和解决方案文件可供下载。 Microsoft Channel 9 网站上提供了此过程的 20 分钟视频演示(代码略有不同):PnP 预配引擎入门。
创建并准备一个 Visual Studio 项目
首先,创建一个 Visual Studio 项目。 在此示例中,为简单起见,我们创建一个基本的控制台应用程序,通过使用预配框架的 PnP 核心库来实现 PnP 预配引擎。 但是若要支持该示例解决方案,我们必须为 PnP 核心库下载和安装预配框架。
打开 Visual Studio,然后选择“文件”>“新建”>“项目”。
在“新建项目”向导中,选择“Visual C#”,然后选择“控制台应用程序”。
将项目命名为“程序”,然后选择“确定”。 (你可以将项目命名为任何名称,但请注意,此演练将引用“程序”作为项目名称。)
从 SharePointPnPCore 包下载并安装 NuGet 包形式的 PnP 核心库。
注意
有三种库版本: 一个版本是 SharePointPnPCoreOnline 库,面向 SharePoint Online 和 Office 365。 其他版本为 SharePointPnPCore2013 和 SharePointPnPCore2016,分别针对 SharePoint 2013 和 SharePoint 2016 本地版本。
通过转到 NuGet 客户端安装程序安装 NuGet 客户端。
安装 NuGet 客户端后,运行 NuGet 包管理器。 右键单击 Visual Studio“解决方案资源管理器”中的“引用”节点,然后选择“管理 NuGet 包”。
在程序包管理器中,选择“浏览”,然后输入搜索词 SharePoint PnP 以公开 SharePointPnPCoreOnline 库。
按照说明下载和安装 SharePointPnPCoreOnline 库,按照给定的说明执行相关操作。
After the PnP Core library is referenced in your Visual Studio project, all library members are available to you as extension methods on existing object instances, for example, web and list instances.
确保 Program.cs 文件中包含以下所有
using
语句。using Microsoft.SharePoint.Client; using OfficeDevPnP.Core.Framework.Provisioning.Connectors; using OfficeDevPnP.Core.Framework.Provisioning.Model; using OfficeDevPnP.Core.Framework.Provisioning.ObjectHandlers; using OfficeDevPnP.Core.Framework.Provisioning.Providers.Xml; using System; using System.Net; using System.Security; using System.Threading;
创建、提取和保留预配模板
项目设置好后,可创建网站自定义设置。 你可以手动或通过指向想要使用其设计的网站来完成。 只需将所选网站设计另存为预配模板即可,或者可以混合使用这两种方法。 在此示例中,我们只需指向现有网站,将其编写的外观和网站项目(而不是内容)另存为预配模板。
若要开始,需要连接到要将其构建为设置模版模型的网站。 我们先来收集连接信息,包括用户名、密码和源 URL 等信息。
从用户那里收集连接信息。 在程序的
Main
例程中,我们执行了三个简单的操作:收集连接信息、获取预配模板和应用预配模板。 复杂任务是通过我们接下来定义的 GetProvisioningTemplate 和 ApplyProvisioningTemplate 方法来完成的。static void Main(string[] args) { ConsoleColor defaultForeground = Console.ForegroundColor; // Collect information string templateWebUrl = GetInput("Enter the URL of the template site: ", false, defaultForeground); string targetWebUrl = GetInput("Enter the URL of the target site: ", false, defaultForeground); string userName = GetInput("Enter your user name:", false, defaultForeground); string pwdS = GetInput("Enter your password:", true, defaultForeground); SecureString pwd = new SecureString(); foreach (char c in pwdS.ToCharArray()) pwd.AppendChar(c); // GET the template from existing site and serialize // Serializing the template for later reuse is optional ProvisioningTemplate template = GetProvisioningTemplate(defaultForeground, templateWebUrl, userName, pwd); // APPLY the template to new site from ApplyProvisioningTemplate(targetWebUrl, userName, pwd, template); // Pause and modify the UI to indicate that the operation is complete Console.ForegroundColor = ConsoleColor.White; Console.WriteLine("We're done. Press Enter to continue."); Console.ReadLine(); }
创建和使用私有 GetInput 方法来获取所需的用户凭据。
private static string GetInput(string label, bool isPassword, ConsoleColor defaultForeground) { Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("{0} : ", label); Console.ForegroundColor = defaultForeground; string value = ""; for (ConsoleKeyInfo keyInfo = Console.ReadKey(true); keyInfo.Key != ConsoleKey.Enter; keyInfo = Console.ReadKey(true)) { if (keyInfo.Key == ConsoleKey.Backspace) { if (value.Length > 0) { value = value.Remove(value.Length - 1); Console.SetCursorPosition(Console.CursorLeft - 1, Console.CursorTop); Console.Write(" "); Console.SetCursorPosition(Console.CursorLeft - 1, Console.CursorTop); } } else if (keyInfo.Key != ConsoleKey.Enter) { if (isPassword) { Console.Write("*"); } else { Console.Write(keyInfo.KeyChar); } value += keyInfo.KeyChar; } } Console.WriteLine(""); return value; }
指向作为我们预配模板的模型的站点。 使用单行代码在源网站上执行 GET 的同时,请查看
GetProvisioningTemplate()
,即我们定义的 GET 方法。private static ProvisioningTemplate GetProvisioningTemplate(ConsoleColor defaultForeground, string webUrl, string userName, SecureString pwd) { using (var ctx = new ClientContext(webUrl)) { // ctx.Credentials = new NetworkCredentials(userName, pwd); ctx.Credentials = new SharePointOnlineCredentials(userName, pwd); ctx.RequestTimeout = Timeout.Infinite; // Just to output the site details Web web = ctx.Web; ctx.Load(web, w => w.Title); ctx.ExecuteQueryRetry(); Console.ForegroundColor = ConsoleColor.White; Console.WriteLine("Your site title is:" + ctx.Web.Title); Console.ForegroundColor = defaultForeground; ProvisioningTemplateCreationInformation ptci = new ProvisioningTemplateCreationInformation(ctx.Web); // Create FileSystemConnector to store a temporary copy of the template ptci.FileConnector = new FileSystemConnector(@"c:\temp\pnpprovisioningdemo", ""); ptci.PersistComposedLookFiles = true; ptci.ProgressDelegate = delegate(String message, Int32 progress, Int32 total) { // Only to output progress for console UI Console.WriteLine("{0:00}/{1:00} - {2}", progress, total, message); }; // Execute actual extraction of the template ProvisioningTemplate template = ctx.Web.GetProvisioningTemplate(ptci); // We can serialize this template to save and reuse it // Optional step XMLTemplateProvider provider = new XMLFileSystemTemplateProvider(@"c:\temp\pnpprovisioningdemo", ""); provider.SaveAs(template, "PnPProvisioningDemo.xml"); return template; } }
在前面的代码段中,我们还定义了 ProvisioningTemplateCreationInformation 变量 pcti。 此变量为我们提供了可与模板一起保存项目相关信息的选项。
创建文件系统连接器对象,以便我们可以存储将应用到其他网站的设置模板的临时副本。
注意
此为可选步骤。 不需要将预配模板系列化到 XML。 在此阶段,模板仅为 C# 代码。 序列化不仅是可选的,还可以使用你喜欢的任何序列化格式。
只需使用此单行代码即可执行预配模板提取操作。
ProvisioningTemplate template = ctx.Web.GetProvisioningTemplate(ptci);
(可选)保存并存储序列化版本的预配模板,以便可以重复使用。 可以通过你想要的任何格式来序列化预配模板。 在此示例中,我们序列化为名为 PnPProvisioningDemo.xml 的 XML 文件。 文件本身是我们为其提供文件系统位置的 XMLFileSystemTemplateProvider 对象。
将预配模板应用到新的或现有的网站
提取、保存和保留预配模板后,下一步也是最后一步,就是使用 ApplyProvisioningTemplate 方法将该预配模板应用到新的 SharePoint 网站集。
获取访问目标网站的凭据。
// ctx.Credentials = new NetworkCredentials(userName, pwd); ctx.Credentials = new SharePointOnlineCredentials(userName, pwd); ctx.RequestTimeout = Timeout.Infinite;
使用辅助方法 ProvisioningTemplateApplyingInformation 捕获使用 ProvisioningTemplateCreationInformation 方法存储的网站项目。
ProvisioningTemplateApplyingInformation ptai = new ProvisioningTemplateApplyingInformation(); ptai.ProgressDelegate = delegate(String message, Int32 progress, Int32 total) { Console.WriteLine("{0:00}/{1:00} - {2}", progress, total, message); };
获取资产到文件连接器的关联。
// Associate file connector for assets FileSystemConnector connector = new FileSystemConnector(@"c:\temp\pnpprovisioningdemo", ""); template.Connector = connector;
(可选)由于设置模板是一个对象实例,因此,我们可以编写代码来实时自定义网站项目。 在此实例中,我们将添加一个新的"联系人"列表。
// Because the template is actual object, we can modify this using code as needed template.Lists.Add(new ListInstance() { Title = "PnP Sample Contacts", Url = "lists/PnPContacts", TemplateType = (Int32)ListTemplateType.Contacts, EnableAttachments = true });
重新使用一行代码,将预配模版应用到新网站。
web.ApplyProvisioningTemplate(template, ptai);
整体
ApplyProvisioningTemplate()
方法实现如下。private static void ApplyProvisioningTemplate(string targetWebUrl, string userName, SecureString pwd, ProvisioningTemplate template) { using (var ctx = new ClientContext(targetWebUrl)) { // ctx.Credentials = new NetworkCredentials(userName, pwd); ctx.Credentials = new SharePointOnlineCredentials(userName, pwd); ctx.RequestTimeout = Timeout.Infinite; Web web = ctx.Web; ProvisioningTemplateApplyingInformation ptai = new ProvisioningTemplateApplyingInformation(); ptai.ProgressDelegate = delegate (String message, Int32 progress, Int32 total) { Console.WriteLine("{0:00}/{1:00} - {2}", progress, total, message); }; // Associate file connector for assets FileSystemConnector connector = new FileSystemConnector(@"c:\temp\pnpprovisioningdemo", ""); template.Connector = connector; // Because the template is actual object, we can modify this using code as needed template.Lists.Add(new ListInstance() { Title = "PnP Sample Contacts", Url = "lists/PnPContacts", TemplateType = (Int32)ListTemplateType.Contacts, EnableAttachments = true }); web.ApplyProvisioningTemplate(template, ptai); } }