protected override void RunJobInternal(ProvisioningJob job) { SubSiteProvisioningJob ssj = job as SubSiteProvisioningJob; if (ssj == null) { throw new ArgumentException("Invalid job type for SubSiteProvisioningJobHandler."); } CreateSubSite(ssj); }
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); } }
public ActionResult CreateSubSite(CreateSubSiteViewModel model) { switch (model.Step) { case CreateSiteStep.SiteInformation: ModelState.Clear(); // If it is the first time that we are here if (String.IsNullOrEmpty(model.Title)) { model.InheritPermissions = true; using (var ctx = PnPPartnerPackContextProvider.GetAppOnlyClientContext(model.ParentSiteUrl)) { Web web = ctx.Web; ctx.Load(web, w => w.Language, w => w.RegionalSettings.TimeZone); ctx.ExecuteQueryRetry(); model.Language = (Int32)web.Language; model.TimeZone = web.RegionalSettings.TimeZone.Id; } } break; case CreateSiteStep.TemplateParameters: if (!ModelState.IsValid) { model.Step = CreateSiteStep.SiteInformation; } else { if (!String.IsNullOrEmpty(model.ProvisioningTemplateUrl) && model.ProvisioningTemplateUrl.IndexOf(PnPPartnerPackConstants.PnPProvisioningTemplates) > 0) { String templateSiteUrl = model.ProvisioningTemplateUrl.Substring(0, model.ProvisioningTemplateUrl.IndexOf(PnPPartnerPackConstants.PnPProvisioningTemplates)); String templateFileName = model.ProvisioningTemplateUrl.Substring(model.ProvisioningTemplateUrl.IndexOf(PnPPartnerPackConstants.PnPProvisioningTemplates) + PnPPartnerPackConstants.PnPProvisioningTemplates.Length + 1); String templateFolder = String.Empty; if (templateFileName.IndexOf("/") > 0) { templateFolder = templateFileName.Substring(0, templateFileName.LastIndexOf("/") - 1); templateFileName = templateFileName.Substring(templateFolder.Length + 1); } model.TemplateParameters = PnPPartnerPackUtilities.GetProvisioningTemplateParameters( templateSiteUrl, templateFolder, templateFileName); } } break; case CreateSiteStep.SiteCreated: AntiForgery.Validate(); if (ModelState.IsValid) { // Prepare the Job to provision the Sub Site SubSiteProvisioningJob job = new SubSiteProvisioningJob(); // Prepare all the other information about the Provisioning Job job.SiteTitle = model.Title; job.Description = model.Description; job.Language = model.Language; job.TimeZone = model.TimeZone; job.ParentSiteUrl = model.ParentSiteUrl; job.RelativeUrl = model.RelativeUrl; job.SitePolicy = model.SitePolicy; job.Owner = ClaimsPrincipal.Current.Identity.Name; job.ProvisioningTemplateUrl = model.ProvisioningTemplateUrl; job.InheritPermissions = model.InheritPermissions; job.Title = String.Format("Provisioning of Sub Site \"{1}\" with Template \"{0}\" by {2}", job.ProvisioningTemplateUrl, job.RelativeUrl, job.Owner); job.TemplateParameters = model.TemplateParameters; model.JobId = ProvisioningRepositoryFactory.Current.EnqueueProvisioningJob(job); } break; default: break; } return(PartialView(model.Step.ToString(), model)); }
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)) { context.RequestTimeout = Timeout.Infinite; // Get a reference to the parent Web Web parentWeb = context.Web; // Load the template from the source Templates Provider if (!String.IsNullOrEmpty(job.TemplatesProviderTypeName)) { ProvisioningTemplate template = null; var templatesProvider = PnPPartnerPackSettings.TemplatesProviders[job.TemplatesProviderTypeName]; if (templatesProvider != null) { template = templatesProvider.GetProvisioningTemplate(job.ProvisioningTemplateUrl); } if (template != null) { // 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; // Use the BaseSiteTemplate of the template, if any, otherwise // fallback to the pre-configured site template (i.e. STS#0) newWeb.WebTemplate = !String.IsNullOrEmpty(template.BaseSiteTemplate) ? template.BaseSiteTemplate : 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); // 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); }; // Exclude handlers not supported in App-Only ptai.HandlersToProcess ^= OfficeDevPnP.Core.Framework.Provisioning.Model.Handlers.TermGroups; ptai.HandlersToProcess ^= OfficeDevPnP.Core.Framework.Provisioning.Model.Handlers.SearchSettings; // Configure template parameters foreach (var key in template.Parameters.Keys) { if (job.TemplateParameters.ContainsKey(key)) { template.Parameters[key] = job.TemplateParameters[key]; } } // Fixup Title and Description template.WebSettings.Title = job.SiteTitle; template.WebSettings.Description = job.Description; // Apply the template to the target site web.ApplyProvisioningTemplate(template, ptai); // Save the template information in the target site var info = new SiteTemplateInfo() { TemplateProviderType = job.TemplatesProviderTypeName, TemplateUri = job.ProvisioningTemplateUrl, TemplateParameters = template.Parameters, AppliedOn = DateTime.Now, }; var jsonInfo = JsonConvert.SerializeObject(info); web.SetPropertyBagValue(PnPPartnerPackConstants.PropertyBag_TemplateInfo, jsonInfo); // Set site policy template if (!String.IsNullOrEmpty(job.SitePolicy)) { web.ApplySitePolicy(job.SitePolicy); } // Apply Tenant Branding, if requested if (job.ApplyTenantBranding) { var brandingSettings = PnPPartnerPackUtilities.GetTenantBrandingSettings(); using (var repositoryContext = PnPPartnerPackContextProvider.GetAppOnlyClientContext( PnPPartnerPackSettings.InfrastructureSiteUrl)) { var brandingTemplate = BrandingJobHandler.PrepareBrandingTemplate(repositoryContext, brandingSettings); // Fixup Title and Description brandingTemplate.WebSettings.Title = job.SiteTitle; brandingTemplate.WebSettings.Description = job.Description; BrandingJobHandler.ApplyBrandingOnWeb(web, brandingSettings, brandingTemplate); } } Console.WriteLine("Applyed Provisioning Template \"{0}\" to site.", job.ProvisioningTemplateUrl); } } } }
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)) { context.RequestTimeout = Timeout.Infinite; // Get a reference to the parent Web Web parentWeb = context.Web; // Load the template from the source Templates Provider if (!String.IsNullOrEmpty(job.TemplatesProviderTypeName)) { ProvisioningTemplate template = null; var templatesProvider = PnPPartnerPackSettings.TemplatesProviders[job.TemplatesProviderTypeName]; if (templatesProvider != null) { template = templatesProvider.GetProvisioningTemplate(job.ProvisioningTemplateUrl); } if (template != null) { // 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; // Use the BaseSiteTemplate of the template, if any, otherwise // fallback to the pre-configured site template (i.e. STS#0) newWeb.WebTemplate = !String.IsNullOrEmpty(template.BaseSiteTemplate) ? template.BaseSiteTemplate : 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); // 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); }; // Exclude handlers not supported in App-Only ptai.HandlersToProcess ^= OfficeDevPnP.Core.Framework.Provisioning.Model.Handlers.TermGroups; ptai.HandlersToProcess ^= OfficeDevPnP.Core.Framework.Provisioning.Model.Handlers.SearchSettings; // Configure template parameters foreach (var key in template.Parameters.Keys) { if (job.TemplateParameters.ContainsKey(key)) { template.Parameters[key] = job.TemplateParameters[key]; } } // Fixup Title and Description template.WebSettings.Title = job.SiteTitle; template.WebSettings.Description = job.Description; // Apply the template to the target site web.ApplyProvisioningTemplate(template, ptai); // Save the template information in the target site var info = new SiteTemplateInfo() { TemplateProviderType = job.TemplatesProviderTypeName, TemplateUri = job.ProvisioningTemplateUrl, TemplateParameters = template.Parameters, AppliedOn = DateTime.Now, }; var jsonInfo = JsonConvert.SerializeObject(info); web.SetPropertyBagValue(PnPPartnerPackConstants.PropertyBag_TemplateInfo, jsonInfo); // Set site policy template if (!String.IsNullOrEmpty(job.SitePolicy)) { web.ApplySitePolicy(job.SitePolicy); } // Apply Tenant Branding, if requested if (job.ApplyTenantBranding) { var brandingSettings = PnPPartnerPackUtilities.GetTenantBrandingSettings(); using (var repositoryContext = PnPPartnerPackContextProvider.GetAppOnlyClientContext( PnPPartnerPackSettings.InfrastructureSiteUrl)) { var brandingTemplate = BrandingJobHandler.PrepareBrandingTemplate(repositoryContext, brandingSettings); // Fixup Title and Description brandingTemplate.WebSettings.Title = job.SiteTitle; brandingTemplate.WebSettings.Description = job.Description; BrandingJobHandler.ApplyBrandingOnWeb(web, brandingSettings, brandingTemplate); } } Console.WriteLine("Applyed Provisioning Template \"{0}\" to site.", job.ProvisioningTemplateUrl); } } } }
public ActionResult CreateSubSite(CreateSubSiteViewModel model) { PnPPartnerPackSettings.ParentSiteUrl = model.ParentSiteUrl; if (model.Step == CreateSiteStep.SiteInformation) { ModelState.Clear(); // If it is the first time that we are here if (String.IsNullOrEmpty(model.Title)) { model.InheritPermissions = true; using (var ctx = PnPPartnerPackContextProvider.GetAppOnlyClientContext(model.ParentSiteUrl)) { Web web = ctx.Web; ctx.Load(web, w => w.Language, w => w.RegionalSettings.TimeZone); ctx.ExecuteQueryRetry(); model.Language = (Int32)web.Language; model.TimeZone = web.RegionalSettings.TimeZone.Id; } } } if (model.Step == CreateSiteStep.TemplateParameters) { if (!ModelState.IsValid) { model.Step = CreateSiteStep.SiteInformation; } else { if (!String.IsNullOrEmpty(model.ProvisioningTemplateUrl) && !String.IsNullOrEmpty(model.TemplatesProviderTypeName)) { var templatesProvider = PnPPartnerPackSettings.TemplatesProviders[model.TemplatesProviderTypeName]; if (templatesProvider != null) { var template = templatesProvider.GetProvisioningTemplate(model.ProvisioningTemplateUrl); model.TemplateParameters = template.Parameters; } if (model.TemplateParameters == null || model.TemplateParameters.Count == 0) { model.Step = CreateSiteStep.SiteCreated; } } } } if (model.Step == CreateSiteStep.SiteCreated) { AntiForgery.Validate(); if (ModelState.IsValid) { // Prepare the Job to provision the Sub Site SubSiteProvisioningJob job = new SubSiteProvisioningJob(); // Prepare all the other information about the Provisioning Job job.SiteTitle = model.Title; job.Description = model.Description; job.Language = model.Language; job.TimeZone = model.TimeZone; job.ParentSiteUrl = model.ParentSiteUrl; job.RelativeUrl = model.RelativeUrl; job.SitePolicy = model.SitePolicy; job.Owner = ClaimsPrincipal.Current.Identity.Name; job.ApplyTenantBranding = model.ApplyTenantBranding; job.ProvisioningTemplateUrl = model.ProvisioningTemplateUrl; job.TemplatesProviderTypeName = model.TemplatesProviderTypeName; job.InheritPermissions = model.InheritPermissions; job.Title = String.Format("Provisioning of Sub Site \"{1}\" with Template \"{0}\" by {2}", job.ProvisioningTemplateUrl, job.RelativeUrl, job.Owner); job.TemplateParameters = model.TemplateParameters; model.JobId = ProvisioningRepositoryFactory.Current.EnqueueProvisioningJob(job); } } return(PartialView(model.Step.ToString(), model)); }
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)) { context.RequestTimeout = Timeout.Infinite; // Get a reference to the parent Web Web parentWeb = context.Web; // Load the template from the source Templates Provider if (!String.IsNullOrEmpty(job.TemplatesProviderTypeName)) { ProvisioningTemplate template = null; var templatesProvider = PnPPartnerPackSettings.TemplatesProviders[job.TemplatesProviderTypeName]; if (templatesProvider != null) { template = templatesProvider.GetProvisioningTemplate(job.ProvisioningTemplateUrl); } if (template != null) { // 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; // Use the BaseSiteTemplate of the template, if any, otherwise // fallback to the pre-configured site template (i.e. STS#0) newWeb.WebTemplate = !String.IsNullOrEmpty(template.BaseSiteTemplate) ? template.BaseSiteTemplate : PnPPartnerPackSettings.DefaultSiteTemplate; Web web = parentWeb.Webs.Add(newWeb); context.ExecuteQueryRetry(); if (template.ExtensibilityHandlers.Any()) { // Clone Context pointing to Sub Site (needed for calling custom Extensibility Providers from the pnp template passing the right ClientContext) string newWeburl = web.EnsureProperty(w => w.Url); ClientContext webClientContext = context.Clone(newWeburl); web = webClientContext.Web; } // Create sub-web unique groups if (!job.InheritPermissions) { web.CreateDefaultAssociatedGroups(string.Empty, string.Empty, string.Empty); context.ExecuteQueryRetry(); } Console.WriteLine("Site \"{0}\" created.", subSiteUrl); // Apply the Provisioning Template Console.WriteLine("Applying Provisioning Template \"{0}\" to site.", job.ProvisioningTemplateUrl); // 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 = (message, type) => { switch (type) { case ProvisioningMessageType.Warning: { Console.WriteLine("{0} - {1}", type, message); break; } case ProvisioningMessageType.Progress: { var activity = message; if (message.IndexOf("|") > -1) { var messageSplitted = message.Split('|'); if (messageSplitted.Length == 4) { var status = messageSplitted[0]; var statusDescription = messageSplitted[1]; var current = double.Parse(messageSplitted[2]); var total = double.Parse(messageSplitted[3]); var percentage = Convert.ToInt32((100 / total) * current); Console.WriteLine("{0} - {1} - {2}", percentage, status, statusDescription); } else { Console.WriteLine(activity); } } else { Console.WriteLine(activity); } break; } case ProvisioningMessageType.Completed: { Console.WriteLine(type); break; } } }; ptai.ProgressDelegate = (message, step, total) => { var percentage = Convert.ToInt32((100 / Convert.ToDouble(total)) * Convert.ToDouble(step)); Console.WriteLine("{0:00}/{1:00} - {2} - {3}", step, total, percentage, message); }; // Exclude handlers not supported in App-Only ptai.HandlersToProcess ^= OfficeDevPnP.Core.Framework.Provisioning.Model.Handlers.TermGroups; ptai.HandlersToProcess ^= OfficeDevPnP.Core.Framework.Provisioning.Model.Handlers.SearchSettings; // Configure template parameters foreach (var key in template.Parameters.Keys) { if (job.TemplateParameters.ContainsKey(key)) { template.Parameters[key] = job.TemplateParameters[key]; } } // Fixup Title and Description if (template.WebSettings != null) { template.WebSettings.Title = job.SiteTitle; template.WebSettings.Description = job.Description; } // Replace existing structural navigation on target site if (template.Navigation != null && template.Navigation.CurrentNavigation != null && template.Navigation.CurrentNavigation.StructuralNavigation != null && (template.Navigation.CurrentNavigation.NavigationType == CurrentNavigationType.Structural || template.Navigation.CurrentNavigation.NavigationType == CurrentNavigationType.StructuralLocal)) { template.Navigation.CurrentNavigation.StructuralNavigation.RemoveExistingNodes = true; } // Replace existing Structural Global Navigation on target site if (template.Navigation != null && template.Navigation.GlobalNavigation != null && template.Navigation.GlobalNavigation.StructuralNavigation != null && template.Navigation.GlobalNavigation.NavigationType == GlobalNavigationType.Structural) { template.Navigation.GlobalNavigation.StructuralNavigation.RemoveExistingNodes = true; } // Apply the template to the target site web.ApplyProvisioningTemplate(template, ptai); // Save the template information in the target site var info = new SiteTemplateInfo() { TemplateProviderType = job.TemplatesProviderTypeName, TemplateUri = job.ProvisioningTemplateUrl, TemplateParameters = template.Parameters, AppliedOn = DateTime.Now, }; var jsonInfo = JsonConvert.SerializeObject(info); web.SetPropertyBagValue(PnPPartnerPackConstants.PropertyBag_TemplateInfo, jsonInfo); // Set site policy template if (!String.IsNullOrEmpty(job.SitePolicy)) { web.ApplySitePolicy(job.SitePolicy); } // Apply Tenant Branding, if requested if (job.ApplyTenantBranding) { var brandingSettings = PnPPartnerPackUtilities.GetTenantBrandingSettings(); using (var repositoryContext = PnPPartnerPackContextProvider.GetAppOnlyClientContext( PnPPartnerPackSettings.InfrastructureSiteUrl)) { var brandingTemplate = BrandingJobHandler.PrepareBrandingTemplate(repositoryContext, brandingSettings); BrandingJobHandler.ApplyBrandingOnWeb(web, brandingSettings, brandingTemplate); // Fixup Title and Description if (brandingTemplate != null) { if (brandingTemplate.WebSettings != null) { brandingTemplate.WebSettings.Title = job.SiteTitle; brandingTemplate.WebSettings.Description = job.Description; } // TO-DO: Need to handle exception here as there are multiple webs inside this where BrandingJobHandler.ApplyBrandingOnWeb(web, brandingSettings, brandingTemplate); } } } Console.WriteLine("Applied Provisioning Template \"{0}\" to site.", job.ProvisioningTemplateUrl); } } } }
private void CreateSubSite(SubSiteProvisioningJob job) { using (PnPMonitoredScope Log = new PnPMonitoredScope("CreateSubSite")) { // get provisioning template var provisioningTemplate = GetProvisioningTemplate(job.PnPTemplate); if (provisioningTemplate != null) { job.BaseTemplate = string.IsNullOrEmpty(provisioningTemplate.BaseSiteTemplate) ? (string.IsNullOrEmpty(job.BaseTemplate) ? ConfigurationHelper.GetConfiguration.BaseSiteTemplate : job.BaseTemplate) : provisioningTemplate.BaseSiteTemplate; } else { job.BaseTemplate = string.IsNullOrEmpty(job.BaseTemplate) ? ConfigurationHelper.GetConfiguration.BaseSiteTemplate : job.BaseTemplate; } Web newWeb = null; using (var siteContext = AppOnlyContextProvider.GetAppOnlyContext(job.ParentWebUrl)) { Web parentWeb = siteContext.Web; siteContext.Load(parentWeb, w => w.Language, w => w.RegionalSettings.TimeZone); siteContext.ExecuteQueryRetry(); if (parentWeb.WebExists(job.RelativeUrl)) { Log.LogError($"Web with url \"{job.RelativeUrl}\" already exists."); newWeb = parentWeb.GetWeb(job.RelativeUrl); siteContext.Load(newWeb); siteContext.ExecuteQueryRetry(); } else { Log.LogInfo($"Creating web \"{job.RelativeUrl}\" with template {job.BaseTemplate}"); try { // Create the new sub site as a new child Web newWeb = parentWeb.CreateWeb(new SiteEntity() { Title = job.Title, Description = job.Description, Lcid = job.Language, Url = job.RelativeUrl, Template = job.BaseTemplate }, job.InheritPermissions, job.InheritNavigation); } catch (Exception exception) { if (parentWeb.WebExists(job.RelativeUrl)) { parentWeb.DeleteWeb(job.RelativeUrl); } throw exception; } } if (provisioningTemplate != null) { Log.LogInfo($"Applying provisioning template {provisioningTemplate.DisplayName}"); ApplyProvisioningTemplate(provisioningTemplate, newWeb); } Log.LogInfo($"Web {job.RelativeUrl} provisioned successfully."); } } }