Forum Discussion

Soheilsd's avatar
Soheilsd
Copper Contributor
Jul 29, 2019

Save as template again!!!

I am wondering if I can save a team site on SharePoint online as a template in a simple way??!!

not using the PnP provisioning its too complicated...

or is there a complete example of pnp code that works in visual studio??

  • paulpascha's avatar
    paulpascha
    Bronze Contributor
    Just wondering, why do you consider the PnP provisioning to be too complicated? You are looking for a solution from a Developer's perspective. With the PnP NuGet packages installed in your project, "Save as template" is basically just 1 line of code (web.GetProvisioningTemplate). Applying a template to another site is also just 1 line of code (web.ApplyProvisioningTemplate).

    A sample console application using the above techniques can be found here:
    https://docs.microsoft.com/en-us/sharepoint/dev/solution-guidance/provisioning-console-application-sample

    For SharePoint Online modern sites you can make use of Site Designs and Site Scripts. You could combine these with PnP provisioning as well.
    https://docs.microsoft.com/en-us/sharepoint/dev/declarative-customization/site-design-overview

    Hope this helps!
    • Soheilsd's avatar
      Soheilsd
      Copper Contributor

      hipaulpascha 

      this is my code

      It works fine when i press start and go to the end of it but my destination site doesn't change...!!

       

       

       

       

      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Text;
      using System.Threading.Tasks;
      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.Net;
      using System.Security;
      using System.Threading;
      namespace Program
      {
      class Program
      {
      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(defaultForeground, 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();
      }

      private static void ApplyProvisioningTemplate(ConsoleColor defaultForeground, string targetWebUrl, string userName, SecureString pwd, ProvisioningTemplate template)
      {

      }

      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;
      }

      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");


      ProvisioningTemplate temp= ctx.Web.GetProvisioningTemplate(ptci);

      // ctx.Credentials = new NetworkCredentials(userName, pwd);
      ctx.Credentials = new SharePointOnlineCredentials(userName, pwd);
      ctx.RequestTimeout = Timeout.Infinite;
      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);

      return template;


      }


      }

      }

      }

       

      • paulpascha's avatar
        paulpascha
        Bronze Contributor
        I can see from your code you don't do anything to your destination site. Your ApplyProvisioningTemplate method is empty and in your GetProvisioningTemplate method you're applying a modified template to the web you've specified in templateWebUrl. So it seems (haven't run your code) your source site is ultimately changed to include a List with Title "PnP Sample Contacts".
  • Do you want to save a template from modern or classic team site?

    What needs to be included in the template?

Resources