private static void ApplyProvisioningTemplateToSite(ClientContext context, String siteUrl, String folder, String fileName, Dictionary<String, String> parameters = null, Handlers handlers = Handlers.All)
        {
            // Configure the XML file system provider
            XMLTemplateProvider provider =
                new XMLSharePointTemplateProvider(context, siteUrl,
                    PnPPartnerPackConstants.PnPProvisioningTemplates +
                    (!String.IsNullOrEmpty(folder) ? "/" + folder : String.Empty));

            // Load the template from the XML stored copy
            ProvisioningTemplate template = provider.GetTemplate(fileName);
            template.Connector = provider.Connector;

            ProvisioningTemplateApplyingInformation ptai = 
                new ProvisioningTemplateApplyingInformation();

            // We exclude Term Groups because they are not supported in AppOnly
            ptai.HandlersToProcess = handlers;
            ptai.HandlersToProcess ^= Handlers.TermGroups;

            // Handle any custom parameter
            if (parameters != null)
            {
                foreach (var parameter in parameters)
                {
                    template.Parameters.Add(parameter.Key, parameter.Value);
                }
            }

            // Apply the template to the target site
            context.Site.RootWeb.ApplyProvisioningTemplate(template, ptai);
        }
        public static ProvisioningTemplate GetProvisioningTemplate(ClientContext context, String siteUrl, String folder, String fileName)
        {
            // Configure the XML file system provider
            XMLTemplateProvider provider =
                new XMLSharePointTemplateProvider(context, siteUrl,
                    PnPPartnerPackConstants.PnPProvisioningTemplates +
                    (!String.IsNullOrEmpty(folder) ? "/" + folder : String.Empty));

            // Load the template from the XML stored copy
            ProvisioningTemplate template = provider.GetTemplate(fileName);

            return (template);
        }
        private void CreateSubSite(SubSiteProvisioningJob job)
        {
            // Determine the reference URLs and relative paths
            String subSiteUrl = job.RelativeUrl;
            String siteCollectionUrl = PnPPartnerPackUtilities.GetSiteCollectionRootUrl(job.ParentSiteUrl);
            String parentSiteUrl = job.ParentSiteUrl;

            Console.WriteLine("Creating Site \"{0}\" as child Site of \"{1}\".", subSiteUrl, parentSiteUrl);

            using (ClientContext context = PnPPartnerPackContextProvider.GetAppOnlyClientContext(parentSiteUrl))
            {
                // Get a reference to the parent Web
                Web parentWeb = context.Web;

                // Create the new sub site as a new child Web
                WebCreationInformation newWeb = new WebCreationInformation();
                newWeb.Description = job.Description;
                newWeb.Language = job.Language;
                newWeb.Title = job.SiteTitle;
                newWeb.Url = subSiteUrl;
                newWeb.UseSamePermissionsAsParentSite = job.InheritPermissions;
                newWeb.WebTemplate = PnPPartnerPackSettings.DefaultSiteTemplate;

                Web web = parentWeb.Webs.Add(newWeb);
                context.ExecuteQueryRetry();

                Console.WriteLine("Site \"{0}\" created.", subSiteUrl);

                // Apply the Provisioning Template
                Console.WriteLine("Applying Provisioning Template \"{0}\" to site.", 
                    job.ProvisioningTemplateUrl);

                // Determine the reference URLs and file names
                String templatesSiteUrl = job.ProvisioningTemplateUrl.Substring(0,
                    job.ProvisioningTemplateUrl.IndexOf(PnPPartnerPackConstants.PnPProvisioningTemplates));
                String templateFileName = job.ProvisioningTemplateUrl.Substring(job.ProvisioningTemplateUrl.LastIndexOf("/") + 1);

                // Configure the XML file system provider
                XMLTemplateProvider provider =
                    new XMLSharePointTemplateProvider(context, templatesSiteUrl,
                        PnPPartnerPackConstants.PnPProvisioningTemplates);

                // Load the template from the XML stored copy
                ProvisioningTemplate template = provider.GetTemplate(templateFileName);
                template.Connector = provider.Connector;

                // We do intentionally remove taxonomies, which are not supported in the AppOnly Authorization model
                // For further details, see the PnP Partner Pack documentation 
                ProvisioningTemplateApplyingInformation ptai =
                    new ProvisioningTemplateApplyingInformation();
                ptai.HandlersToProcess ^=
                    OfficeDevPnP.Core.Framework.Provisioning.Model.Handlers.TermGroups;

                // Configure template parameters
                foreach (var key in template.Parameters.Keys)
                {
                    if (job.TemplateParameters.ContainsKey(key))
                    {
                        template.Parameters[key] = job.TemplateParameters[key];
                    }
                }

                // Apply the template to the target site
                web.ApplyProvisioningTemplate(template, ptai);

                Console.WriteLine("Applyed Provisioning Template \"{0}\" to site.",
                    job.ProvisioningTemplateUrl);
            }
        }
        private void CreateSiteCollection(SiteCollectionProvisioningJob job)
        {
            Console.WriteLine("Creating Site Collection \"{0}\".", job.RelativeUrl);

            // Define the full Site Collection URL
            String siteUrl = String.Format("{0}{1}",
                PnPPartnerPackSettings.InfrastructureSiteUrl.Substring(0, PnPPartnerPackSettings.InfrastructureSiteUrl.IndexOf("sharepoint.com/") + 14),
                job.RelativeUrl);

            using (var adminContext = PnPPartnerPackContextProvider.GetAppOnlyTenantLevelClientContext())
            {
                // Configure the Site Collection properties
                SiteEntity newSite = new SiteEntity();
                newSite.Description = job.Description;
                newSite.Lcid = (uint)job.Language;
                newSite.Title = job.SiteTitle;
                newSite.Url = siteUrl;
                newSite.SiteOwnerLogin = job.PrimarySiteCollectionAdmin;
                newSite.StorageMaximumLevel = job.StorageMaximumLevel;
                newSite.StorageWarningLevel = job.StorageWarningLevel;
                newSite.Template = PnPPartnerPackSettings.DefaultSiteTemplate;
                newSite.TimeZoneId = job.TimeZone;
                newSite.UserCodeMaximumLevel = job.UserCodeMaximumLevel;
                newSite.UserCodeWarningLevel = job.UserCodeWarningLevel;

                // Create the Site Collection and wait for its creation (we're asynchronous)
                var tenant = new Tenant(adminContext);
                tenant.CreateSiteCollection(newSite, true, true); // TODO: Do we want to empty Recycle Bin?

                Site site = tenant.GetSiteByUrl(siteUrl);
                Web web = site.RootWeb;

                adminContext.Load(site, s => s.Url);
                adminContext.Load(web, w => w.Url);
                adminContext.ExecuteQueryRetry();

                // Enable Secondary Site Collection Administrator
                if (!String.IsNullOrEmpty(job.SecondarySiteCollectionAdmin))
                {
                    Microsoft.SharePoint.Client.User secondaryOwner = web.EnsureUser(job.SecondarySiteCollectionAdmin);
                    secondaryOwner.IsSiteAdmin = true;
                    secondaryOwner.Update();

                    web.SiteUsers.AddUser(secondaryOwner);
                    adminContext.ExecuteQueryRetry();
                }

                Console.WriteLine("Site \"{0}\" created.", site.Url);

                // Check if external sharing has to be enabled
                if (job.ExternalSharingEnabled)
                {
                    EnableExternalSharing(tenant, site);

                    // Enable External Sharing
                    Console.WriteLine("Enabled External Sharing for site \"{0}\".",
                        site.Url);
                }
            }

            // Move to the context of the created Site Collection
            using (ClientContext clientContext = PnPPartnerPackContextProvider.GetAppOnlyClientContext(siteUrl))
            {
                Site site = clientContext.Site;
                Web web = site.RootWeb;

                clientContext.Load(site, s => s.Url);
                clientContext.Load(web, w => w.Url);
                clientContext.ExecuteQueryRetry();

                // Check if we need to enable PnP Partner Pack overrides
                if (job.PartnerPackExtensionsEnabled)
                {
                    // Enable Responsive Design
                    PnPPartnerPackUtilities.EnablePartnerPackOnSite(site.Url);

                    Console.WriteLine("Enabled PnP Partner Pack Overrides on site \"{0}\".",
                        site.Url);
                }

                // Check if the site has to be responsive
                if (job.ResponsiveDesignEnabled)
                {
                    // Enable Responsive Design
                    PnPPartnerPackUtilities.EnableResponsiveDesignOnSite(site.Url);

                    Console.WriteLine("Enabled Responsive Design Template to site \"{0}\".",
                        site.Url);
                }

                // Apply the Provisioning Template
                Console.WriteLine("Applying Provisioning Template \"{0}\" to site.",
                    job.ProvisioningTemplateUrl);

                // Determine the reference URLs and file names
                String templatesSiteUrl = PnPPartnerPackUtilities.GetSiteCollectionRootUrl(job.ProvisioningTemplateUrl);
                String templateFileName = job.ProvisioningTemplateUrl.Substring(job.ProvisioningTemplateUrl.LastIndexOf("/") + 1);

                using (ClientContext repositoryContext = PnPPartnerPackContextProvider.GetAppOnlyClientContext(templatesSiteUrl))
                {
                    // Configure the XML file system provider
                    XMLTemplateProvider provider =
                        new XMLSharePointTemplateProvider(
                            repositoryContext,
                            templatesSiteUrl,
                            PnPPartnerPackConstants.PnPProvisioningTemplates);

                    // Load the template from the XML stored copy
                    ProvisioningTemplate template = provider.GetTemplate(templateFileName);
                    template.Connector = provider.Connector;

                    // We do intentionally remove taxonomies, which are not supported
                    // in the AppOnly Authorization model
                    // For further details, see the PnP Partner Pack documentation
                    ProvisioningTemplateApplyingInformation ptai =
                        new ProvisioningTemplateApplyingInformation();

                    // Write provisioning steps on console log
                    ptai.MessagesDelegate += delegate (string message, ProvisioningMessageType messageType) {
                        Console.WriteLine("{0} - {1}", messageType, messageType);
                    };
                    ptai.ProgressDelegate += delegate (string message, int step, int total) {
                        Console.WriteLine("{0:00}/{1:00} - {2}", step, total, message);
                    };

                    ptai.HandlersToProcess ^=
                        OfficeDevPnP.Core.Framework.Provisioning.Model.Handlers.TermGroups;

                    // Configure template parameters
                    if (job.TemplateParameters != null)
                    {
                        foreach (var key in job.TemplateParameters.Keys)
                        {
                            if (job.TemplateParameters.ContainsKey(key))
                            {
                                template.Parameters[key] = job.TemplateParameters[key];
                            }
                        }
                    }

                    web.ApplyProvisioningTemplate(template, ptai);
                }

                Console.WriteLine("Applyed Provisioning Template \"{0}\" to site.",
                    job.ProvisioningTemplateUrl);
            }
        }
        private static void ApplyProvisioningTemplateToSite(ClientContext context, String siteUrl, String folder, String fileName)
        {
            // Configure the XML file system provider
            XMLTemplateProvider provider =
                new XMLSharePointTemplateProvider(context, siteUrl,
                    PnPPartnerPackConstants.PnPProvisioningTemplates +
                    (!String.IsNullOrEmpty(folder) ? "/" + folder : String.Empty));

            // Load the template from the XML stored copy
            ProvisioningTemplate template = provider.GetTemplate(fileName);
            template.Connector = provider.Connector;

            // Apply the template to the target site
            context.Site.RootWeb.ApplyProvisioningTemplate(template);
        }
        private static void ApplyProvisioningTemplateToSite(ClientContext context, String siteUrl, String folder, String fileName, Dictionary<String, String> parameters = null)
        {
            // Configure the XML file system provider
            XMLTemplateProvider provider =
                new XMLSharePointTemplateProvider(context, siteUrl,
                    PnPPartnerPackConstants.PnPProvisioningTemplates +
                    (!String.IsNullOrEmpty(folder) ? "/" + folder : String.Empty));

            // Load the template from the XML stored copy
            ProvisioningTemplate template = provider.GetTemplate(fileName);
            template.Connector = provider.Connector;

            // Handle any custom parameter
            if (parameters != null)
            {
                foreach (var parameter in parameters)
                {
                    template.Parameters.Add(parameter.Key, parameter.Value);
                }
            }

            // Apply the template to the target site
            context.Site.RootWeb.ApplyProvisioningTemplate(template);
        }
        /// <summary>
        /// Returns a ProvisioningTemplate object based on the XML file with the provided templateName in the library with the provided libraryName
        /// </summary>
        /// <param name="clientContext">Context</param>
        /// <param name="libraryName">Name of the library containing the file</param>
        /// <param name="templateName">Name of the template file</param>
        /// <returns></returns>
        private static ProvisioningTemplate GetProvisioningTemplate(ClientContext clientContext, string libraryName, string templateName)
        {
            Web thisWeb = clientContext.Web;
            clientContext.Load(thisWeb);
            clientContext.ExecuteQuery();

            //Parameters for below XMLSharePointTemplateProvider constructor method are not documented.
            //More info below is taken from parent class method definition here: https://github.com/OfficeDev/PnP/blob/master/OfficeDevPnP.Core/OfficeDevPnP.Core/Framework/Provisioning/Connectors/SharePointConnector.cs

            //ClientContext clientContext: the client context
            //string connectionString: web URL (e.g. https://yourtenant.sharepoint.com/sites/dev)
            //string container: library + folder containing the file (e.g. Documents/MyFolder, or just Documents)
            //Get the XML file
            XMLSharePointTemplateProvider provider = new XMLSharePointTemplateProvider(clientContext, thisWeb.Url, libraryName);

            // Get the available, valid templates
            var templates = provider.GetTemplates();
            foreach (var template1 in templates)
            {
                Console.WriteLine("Found template with ID {0}", template1.Id);
            }
            //Load the template
            ProvisioningTemplate template = provider.GetTemplate(templateName);

            return template;
        }