public static string GetPeoplePickerSearchData() { using (var context = PnPPartnerPackContextProvider.GetAppOnlyClientContext(PnPPartnerPackSettings.InfrastructureSiteUrl)) { return(GetPeoplePickerSearchData(context)); } }
public ActionResult GetTemplateImagePreviewFromPnP(String imagePreviewUri) { if (String.IsNullOrEmpty(imagePreviewUri)) { throw new ArgumentNullException("imagePreviewUri"); } // Recover the original protocol moniker var sourceUrl = imagePreviewUri.Replace("pnps://", "https://").Replace("pnp://", "http://"); var imagePreviewFile = sourceUrl.Substring(sourceUrl.LastIndexOf("/") + 1); var pnpFileUrl = sourceUrl.Substring(0, sourceUrl.LastIndexOf("/")); var pnpFileName = pnpFileUrl.Substring(pnpFileUrl.LastIndexOf("/") + 1); var sourceSiteUrl = PnPPartnerPackUtilities.GetSiteCollectionRootUrl(pnpFileUrl); var sourceSiteFolder = pnpFileUrl.Substring(sourceSiteUrl.Length + 1, pnpFileUrl.LastIndexOf("/") - sourceSiteUrl.Length - 1); using (var repositoryContext = PnPPartnerPackContextProvider.GetAppOnlyClientContext(sourceSiteUrl)) { var repositoryWeb = repositoryContext.Web; repositoryWeb.EnsureProperty(w => w.Url); XMLTemplateProvider provider = new XMLOpenXMLTemplateProvider(pnpFileName, new SharePointConnector(repositoryContext, repositoryWeb.Url, sourceSiteFolder)); var imageFileStream = provider.Connector.GetFileStream(imagePreviewFile); return(base.File(imageFileStream, "image/png")); } }
public ActionResult Index() { IndexViewModel model = new IndexViewModel(); using (var ctx = PnPPartnerPackContextProvider.GetAppOnlyClientContext(PnPPartnerPackSettings.InfrastructureSiteUrl)) { // Track usage of the PnP Partner Pack ctx.ClientTag = "SPDev:PartnerPack"; Web web = ctx.Web; ctx.Load(web, w => w.Title, w => w.Url); ctx.ExecuteQuery(); model.InfrastructuralSiteUrl = web.Url; } var currentUser = UserUtility.GetCurrentUser(); if (currentUser != null) { model.CurrentUserPrincipalName = currentUser.UserPrincipalName; } else { model.CurrentUserPrincipalName = ClaimsPrincipal.Current.Identity.Name; } return(View(model)); }
private void UpdateTemplates(RefreshSitesJob job) { // For each Site Collection in the tenant using (var adminContext = PnPPartnerPackContextProvider.GetAppOnlyTenantLevelClientContext()) { var tenant = new Tenant(adminContext); var siteCollections = tenant.GetSiteProperties(0, true); adminContext.Load(siteCollections); adminContext.ExecuteQueryRetry(); foreach (var site in siteCollections) { // Exclude Microsoft NextGen Portals if (!site.Url.ToLower().Contains("/portals/") && !site.Url.ToLower().Contains("-public.sharepoint.com") && !site.Url.ToLower().Contains("-my.sharepoint.com")) { using (var siteContext = PnPPartnerPackContextProvider.GetAppOnlyClientContext(site.Url)) { // Get a reference to the target web var targetWeb = siteContext.Site.RootWeb; // Update the root web of the site collection RefreshSitesJobHandler.UpdateTemplateOnWeb(targetWeb, job); } } } } }
/// <summary> /// Saves a Provisioning Template into the target Global repository /// </summary> /// <param name="job">The Provisioning Template to save</param> public void SaveGlobalProvisioningTemplate(GetProvisioningTemplateJob job) { // Connect to the Infrastructural Site Collection using (var context = PnPPartnerPackContextProvider.GetAppOnlyClientContext(job.SourceSiteUrl)) { SaveProvisioningTemplateInternal(context, job, true); } }
/// <summary> /// Saves a Provisioning Template into the target Local repository /// </summary> /// <param name="siteUrl">The local Site Collection to save to</param> /// <param name="template">The Provisioning Template to save</param> public void SaveLocalProvisioningTemplate(string siteUrl, GetProvisioningTemplateJob job) { // Connect to the Local Site Collection using (var context = PnPPartnerPackContextProvider.GetAppOnlyClientContext(siteUrl)) { PnPPartnerPackUtilities.EnablePartnerPackInfrastructureOnSite(siteUrl); SaveProvisioningTemplateInternal(context, job, false); } }
public ActionResult SaveSiteAsTemplate(SaveTemplateViewModel model, HttpPostedFileBase templateImageFile) { AntiForgery.Validate(); if (ModelState.IsValid) { // Prepare the Job to store the Provisioning Template GetProvisioningTemplateJob job = new GetProvisioningTemplateJob(); // Store the local location for the Provisioning Template, if any String storageLocationUrl = null; // Determine the Scope of the Provisioning Template using (var ctx = PnPPartnerPackContextProvider.GetAppOnlyClientContext(model.SourceSiteUrl)) { Web web = ctx.Web; Web rootWeb = ctx.Site.RootWeb; ctx.Load(web, w => w.Id); ctx.Load(rootWeb, w => w.Url, w => w.Id); ctx.ExecuteQueryRetry(); if (web.Id == rootWeb.Id) { // We are in the Root Site of the Site Collection job.Scope = TemplateScope.Site; storageLocationUrl = rootWeb.Url; } else { // Otherwise we are in a Sub Site of the Site Collection job.Scope = TemplateScope.Web; } } // Prepare all the other information about the Provisioning Job job.Owner = ClaimsPrincipal.Current.Identity.Name; job.FileName = model.FileName; job.IncludeAllTermGroups = model.IncludeAllTermGroups; job.IncludeSearchConfiguration = model.IncludeSearchConfiguration; job.IncludeSiteCollectionTermGroup = model.IncludeSiteCollectionTermGroup; job.IncludeSiteGroups = model.IncludeSiteGroups; job.PersistComposedLookFiles = model.PersistComposedLookFiles; job.SourceSiteUrl = model.SourceSiteUrl; job.Title = model.Title; job.Description = model.Description; job.Location = (ProvisioningTemplateLocation)Enum.Parse(typeof(ProvisioningTemplateLocation), model.Location, true); job.StorageSiteLocationUrl = storageLocationUrl; if (templateImageFile != null && templateImageFile.ContentLength > 0) { job.TemplateImageFile = templateImageFile.InputStream.FixedSizeImageStream(320, 180).ToByteArray(); job.TemplateImageFileName = templateImageFile.FileName; } model.JobId = ProvisioningRepositoryFactory.Current.EnqueueProvisioningJob(job); } return(View(model)); }
public void UpdateProvisioningJob(Guid jobId, ProvisioningJobStatus status, String errorMessage = null) { // Connect to the Infrastructural Site Collection using (var context = PnPPartnerPackContextProvider.GetAppOnlyClientContext(PnPPartnerPackSettings.InfrastructureSiteUrl)) { // Get a reference to the target library Web web = context.Web; List list = web.Lists.GetByTitle(PnPPartnerPackConstants.PnPProvisioningJobs); context.Load(list, l => l.RootFolder); CamlQuery query = new CamlQuery(); query.ViewXml = @"<View> <Query> <Where> <Eq> <FieldRef Name='FileLeafRef' /> <Value Type='Text'>" + jobId + @".job</Value> </Eq> </Where> </Query> </View>"; ListItemCollection items = list.GetItems(query); context.Load(items, includes => includes.IncludeWithDefaultProperties( j => j[PnPPartnerPackConstants.PnPProvisioningJobStatus], j => j[PnPPartnerPackConstants.PnPProvisioningJobError], j => j[PnPPartnerPackConstants.PnPProvisioningJobType]), includes => includes.Include(j => j.File)); context.ExecuteQueryRetry(); if (items.Count > 0) { ListItem jobItem = items[0]; // Update the ProvisioningJob object internal status ProvisioningJob job = GetProvisioningJobStreamFromSharePoint(context, jobItem) .FromJsonStream((String)jobItem[PnPPartnerPackConstants.PnPProvisioningJobType]); job.Status = status; job.ErrorMessage = errorMessage; // Update the SharePoint ListItem behind the Provisioning Job item // jobItem[PnPPartnerPackConstants.ContentTypeIdField] = PnPPartnerPackConstants.PnPProvisioningJobContentTypeId; jobItem[PnPPartnerPackConstants.PnPProvisioningJobStatus] = status.ToString(); jobItem[PnPPartnerPackConstants.PnPProvisioningJobError] = errorMessage; jobItem.Update(); context.ExecuteQueryRetry(); // Update the file list.RootFolder.UploadFile(jobItem.File.Name, job.ToJsonStream(), true); } } }
private void UpdateTemplates(RefreshSingleSiteJob job) { using (var siteContext = PnPPartnerPackContextProvider.GetAppOnlyClientContext(job.TargetSiteUrl)) { // Get a reference to the target web var targetWeb = siteContext.Site.RootWeb; // Update the root web of the site collection RefreshSitesJobHandler.UpdateTemplateOnWeb(targetWeb); } }
public ActionResult Index() { IndexViewModel model = new IndexViewModel(); model.CurrentUserPrincipalName = ClaimsPrincipal.Current.Identity.Name; using (var ctx = PnPPartnerPackContextProvider.GetAppOnlyClientContext(PnPPartnerPackSettings.InfrastructureSiteUrl)) { Web web = ctx.Web; ctx.Load(web, w => w.Title, w => w.Url); ctx.ExecuteQueryRetry(); model.InfrastructuralSiteUrl = web.Url; } return(View(model)); }
public virtual ProvisioningTemplate GetProvisioningTemplate(string templateUri) { // Connect to the target Templates Site Collection using (var context = PnPPartnerPackContextProvider.GetAppOnlyClientContext(TemplatesSiteUrl)) { // Get a reference to the target library Web web = context.Web; web.EnsureProperty(w => w.Url); var templateRelativePath = templateUri.Substring(templateUri.LastIndexOf("/") + 1); // Configure the SharePoint Connector var sharepointConnector = new SharePointConnector(context, web.Url, PnPPartnerPackConstants.PnPProvisioningTemplates); TemplateProviderBase provider = null; // If the target is a .PNP Open XML template if (templateRelativePath.ToLower().EndsWith(".pnp")) { // Configure the Open XML provider for SharePoint provider = new XMLOpenXMLTemplateProvider( new OpenXMLConnector(templateRelativePath, sharepointConnector)); } else { // Otherwise use the .XML template provider for SharePoint provider = new XMLSharePointTemplateProvider(context, web.Url, PnPPartnerPackConstants.PnPProvisioningTemplates); } // Determine the name of the XML file inside the PNP Open XML file, if any var xmlTemplateFile = templateRelativePath.ToLower().Replace(".pnp", ".xml"); // Get the template ProvisioningTemplate template = provider.GetTemplate(xmlTemplateFile); template.Connector = provider.Connector; return(template); } }
private void ApplyBranding(BrandingJob job) { // Use the infrastructural site collection to temporary store the template with color palette and font files using (var repositoryContext = PnPPartnerPackContextProvider.GetAppOnlyClientContext( PnPPartnerPackSettings.InfrastructureSiteUrl)) { var brandingSettings = PnPPartnerPackUtilities.GetTenantBrandingSettings(); ProvisioningTemplate template = PrepareBrandingTemplate(repositoryContext, brandingSettings); // For each Site Collection in the tenant using (var adminContext = PnPPartnerPackContextProvider.GetAppOnlyTenantLevelClientContext()) { var tenant = new Tenant(adminContext); var siteCollections = tenant.GetSiteProperties(0, true); adminContext.Load(siteCollections); adminContext.ExecuteQueryRetry(); foreach (var site in siteCollections) { if (!site.Url.ToLower().Contains("/portals/") && !site.Url.ToLower().Contains("-public.sharepoint.com") && !site.Url.ToLower().Contains("-my.sharepoint.com")) { // Clean-up the template template.WebSettings.MasterPageUrl = null; using (var siteContext = PnPPartnerPackContextProvider.GetAppOnlyClientContext(site.Url)) { // Get a reference to the target web var targetWeb = siteContext.Site.RootWeb; // Update the root web of the site collection ApplyBrandingOnWeb(targetWeb, brandingSettings, template); } } } } } }
public ProvisioningJobInformation GetProvisioningJob(Guid jobId, Boolean includeStream = false) { // Connect to the Infrastructural Site Collection using (var context = PnPPartnerPackContextProvider.GetAppOnlyClientContext(PnPPartnerPackSettings.InfrastructureSiteUrl)) { // Get a reference to the target library Web web = context.Web; List list = web.Lists.GetByTitle(PnPPartnerPackConstants.PnPProvisioningJobs); CamlQuery query = new CamlQuery(); query.ViewXml = @"<View> <Query> <Where> <Eq> <FieldRef Name='FileLeafRef' /> <Value Type='Text'>" + jobId.ToString("D") + @".job</Value> </Eq> </Where> </Query> </View>"; ListItemCollection items = list.GetItems(query); context.Load(items); context.ExecuteQueryRetry(); if (items.Count > 0) { ListItem jobItem = items[0]; return(PrepareJobInformationFromSharePoint(context, jobItem, includeStream)); } else { return(null); } } }
private List <ProvisioningTemplateInformation> SearchProvisioningTemplatesInternal(string searchText, TargetPlatform platforms, TargetScope scope, String cacheKey) { List <ProvisioningTemplateInformation> result = new List <ProvisioningTemplateInformation>(); // Connect to the target Templates Site Collection using (var context = PnPPartnerPackContextProvider.GetAppOnlyClientContext(TemplatesSiteUrl)) { // Get a reference to the target library Web web = context.Web; String platformsCAMLFilter = null; // Build the target Platforms filter if (platforms != TargetPlatform.None && platforms != TargetPlatform.All) { if ((platforms & TargetPlatform.SharePointOnline) == TargetPlatform.SharePointOnline) { platformsCAMLFilter = @"<Eq> <FieldRef Name='PnPProvisioningTemplatePlatform' /> <Value Type='MultiChoice'>SharePoint Online</Value> </Eq>"; } if ((platforms & TargetPlatform.SharePoint2016) == TargetPlatform.SharePoint2016) { if (!String.IsNullOrEmpty(platformsCAMLFilter)) { platformsCAMLFilter = @"<Or>" + platformsCAMLFilter + @" <Eq> <FieldRef Name='PnPProvisioningTemplatePlatform' /> <Value Type='MultiChoice'>SharePoint 2016</Value> </Eq> </Or>"; } else { platformsCAMLFilter = @"<Eq> <FieldRef Name='PnPProvisioningTemplatePlatform' /> <Value Type='MultiChoice'>SharePoint 2016</Value> </Eq>"; } } if ((platforms & TargetPlatform.SharePoint2013) == TargetPlatform.SharePoint2013) { if (!String.IsNullOrEmpty(platformsCAMLFilter)) { platformsCAMLFilter = @"<Or>" + platformsCAMLFilter + @" <Eq> <FieldRef Name='PnPProvisioningTemplatePlatform' /> <Value Type='MultiChoice'>SharePoint 2013</Value> </Eq> </Or>"; } else { platformsCAMLFilter = @"<Eq> <FieldRef Name='PnPProvisioningTemplatePlatform' /> <Value Type='MultiChoice'>SharePoint 2013</Value> </Eq>"; } } try { List list = web.Lists.GetByTitle(PnPPartnerPackConstants.PnPProvisioningTemplates); // Get only Provisioning Templates documents with the specified Scope CamlQuery query = new CamlQuery(); query.ViewXml = @"<View> <Query> <Where>" + (!String.IsNullOrEmpty(platformsCAMLFilter) ? " < And>" : String.Empty) + @" <And> <Eq> <FieldRef Name='PnPProvisioningTemplateScope' /> <Value Type='Choice'>" + scope.ToString() + @"</Value> </Eq> <Eq> <FieldRef Name='ContentType' /> <Value Type=''Computed''>PnPProvisioningTemplate</Value> </Eq> </And>" + platformsCAMLFilter + (!String.IsNullOrEmpty(platformsCAMLFilter) ? "</And>" : String.Empty) + @" </Where> </Query> <ViewFields> <FieldRef Name='Title' /> <FieldRef Name='PnPProvisioningTemplateScope' /> <FieldRef Name='PnPProvisioningTemplatePlatform' /> <FieldRef Name='PnPProvisioningTemplateSourceUrl' /> </ViewFields> </View>"; ListItemCollection items = list.GetItems(query); context.Load(items, includes => includes.Include(i => i.File, i => i[PnPPartnerPackConstants.PnPProvisioningTemplateScope], i => i[PnPPartnerPackConstants.PnPProvisioningTemplatePlatform], i => i[PnPPartnerPackConstants.PnPProvisioningTemplateSourceUrl])); context.ExecuteQueryRetry(); web.EnsureProperty(w => w.Url); // Configure the SharePoint Connector var sharepointConnector = new SharePointConnector(context, web.Url, PnPPartnerPackConstants.PnPProvisioningTemplates); foreach (ListItem item in items) { // Get the template file name and server relative URL item.File.EnsureProperties(f => f.Name, f => f.ServerRelativeUrl); TemplateProviderBase provider = null; // If the target is a .PNP Open XML template if (item.File.Name.ToLower().EndsWith(".pnp")) { // Configure the Open XML provider for SharePoint provider = new XMLOpenXMLTemplateProvider( new OpenXMLConnector(item.File.Name, sharepointConnector)); } else { // Otherwise use the .XML template provider for SharePoint provider = new XMLSharePointTemplateProvider(context, web.Url, PnPPartnerPackConstants.PnPProvisioningTemplates); } // Determine the name of the XML file inside the PNP Open XML file, if any var xmlTemplateFile = item.File.Name.ToLower().Replace(".pnp", ".xml"); // Get the template ProvisioningTemplate template = provider.GetTemplate(xmlTemplateFile); // Prepare the resulting item var templateInformation = new ProvisioningTemplateInformation { // Scope = (TargetScope)Enum.Parse(typeof(TargetScope), (String)item[PnPPartnerPackConstants.PnPProvisioningTemplateScope], true), TemplateSourceUrl = item[PnPPartnerPackConstants.PnPProvisioningTemplateSourceUrl] != null ? ((FieldUrlValue)item[PnPPartnerPackConstants.PnPProvisioningTemplateSourceUrl]).Url : null, TemplateFileUri = String.Format("{0}/{1}/{2}", web.Url, PnPPartnerPackConstants.PnPProvisioningTemplates, item.File.Name), TemplateImageUrl = template.ImagePreviewUrl, DisplayName = template.DisplayName, Description = template.Description, }; #region Determine Scope String targetScope; if (template.Properties.TryGetValue(PnPPartnerPackConstants.TEMPLATE_SCOPE, out targetScope)) { if (String.Equals(targetScope, PnPPartnerPackConstants.TEMPLATE_SCOPE_PARTIAL, StringComparison.InvariantCultureIgnoreCase)) { templateInformation.Scope = TargetScope.Partial; } else if (String.Equals(targetScope, PnPPartnerPackConstants.TEMPLATE_SCOPE_WEB, StringComparison.InvariantCultureIgnoreCase)) { templateInformation.Scope = TargetScope.Web; } else if (String.Equals(targetScope, PnPPartnerPackConstants.TEMPLATE_SCOPE_SITE, StringComparison.InvariantCultureIgnoreCase)) { templateInformation.Scope = TargetScope.Site; } } #endregion #region Determine target Platforms String spoPlatform, sp2016Platform, sp2013Platform; if (template.Properties.TryGetValue(PnPPartnerPackConstants.PLATFORM_SPO, out spoPlatform)) { if (spoPlatform.Equals(PnPPartnerPackConstants.TRUE_VALUE, StringComparison.InvariantCultureIgnoreCase)) { templateInformation.Platforms |= TargetPlatform.SharePointOnline; } } if (template.Properties.TryGetValue(PnPPartnerPackConstants.PLATFORM_SP2016, out sp2016Platform)) { if (sp2016Platform.Equals(PnPPartnerPackConstants.TRUE_VALUE, StringComparison.InvariantCultureIgnoreCase)) { templateInformation.Platforms |= TargetPlatform.SharePoint2016; } } if (template.Properties.TryGetValue(PnPPartnerPackConstants.PLATFORM_SP2013, out sp2013Platform)) { if (sp2013Platform.Equals(PnPPartnerPackConstants.TRUE_VALUE, StringComparison.InvariantCultureIgnoreCase)) { templateInformation.Platforms |= TargetPlatform.SharePoint2013; } } #endregion // If we don't have a search text // or we have a search text and it is contained either // in the DisplayName or in the Description of the template if ((!String.IsNullOrEmpty(searchText) && ((!String.IsNullOrEmpty(template.DisplayName) && template.DisplayName.ToLower().Contains(searchText.ToLower())) || (!String.IsNullOrEmpty(template.Description) && template.Description.ToLower().Contains(searchText.ToLower())))) || String.IsNullOrEmpty(searchText)) { // Add the template to the result result.Add(templateInformation); } } } catch (ServerException) { // In case of any issue, ignore the failing templates } } } CacheItemPolicy policy = new CacheItemPolicy { Priority = CacheItemPriority.Default, AbsoluteExpiration = DateTimeOffset.Now.AddMinutes(30), // Cache results for 30 minutes RemovedCallback = (args) => { if (args.RemovedReason == CacheEntryRemovedReason.Expired) { var removedKey = args.CacheItem.Key; var searchInputs = JsonConvert.DeserializeObject <SharePointSearchCacheKey>(removedKey); var newItem = SearchProvisioningTemplatesInternal( searchInputs.SearchText, searchInputs.Platforms, searchInputs.Scope, removedKey); } }, }; Cache.Set(cacheKey, result, policy); return(result); }
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()) { adminContext.RequestTimeout = Timeout.Infinite; // 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); } }
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)); }
public ProvisioningTemplateInformation[] GetLocalProvisioningTemplates(string siteUrl, TemplateScope scope) { List <ProvisioningTemplateInformation> result = new List <ProvisioningTemplateInformation>(); // Retrieve the Root Site Collection URL siteUrl = PnPPartnerPackUtilities.GetSiteCollectionRootUrl(siteUrl); // Connect to the Infrastructural Site Collection using (var context = PnPPartnerPackContextProvider.GetAppOnlyClientContext(siteUrl)) { // Get a reference to the target library Web web = context.Web; try { List list = web.Lists.GetByTitle(PnPPartnerPackConstants.PnPProvisioningTemplates); // Get only Provisioning Templates documents with the specified Scope CamlQuery query = new CamlQuery(); query.ViewXml = @"<View> <Query> <Where> <And> <Eq> <FieldRef Name='PnPProvisioningTemplateScope' /> <Value Type='Choice'>" + scope.ToString() + @"</Value> </Eq> <Eq> <FieldRef Name='ContentType' /> <Value Type=''Computed''>PnPProvisioningTemplate</Value> </Eq> </And> </Where> </Query> <ViewFields> <FieldRef Name='Title' /> <FieldRef Name='PnPProvisioningTemplateScope' /> <FieldRef Name='PnPProvisioningTemplateSourceUrl' /> </ViewFields> </View>"; ListItemCollection items = list.GetItems(query); context.Load(items, includes => includes.Include(i => i.File, i => i[PnPPartnerPackConstants.PnPProvisioningTemplateScope], i => i[PnPPartnerPackConstants.PnPProvisioningTemplateSourceUrl])); context.ExecuteQueryRetry(); web.EnsureProperty(w => w.Url); foreach (ListItem item in items) { // Configure the XML file system provider XMLTemplateProvider provider = new XMLSharePointTemplateProvider(context, web.Url, PnPPartnerPackConstants.PnPProvisioningTemplates); item.File.EnsureProperties(f => f.Name, f => f.ServerRelativeUrl); ProvisioningTemplate template = provider.GetTemplate(item.File.Name); result.Add(new ProvisioningTemplateInformation { Scope = (TemplateScope)Enum.Parse(typeof(TemplateScope), (String)item[PnPPartnerPackConstants.PnPProvisioningTemplateScope], true), TemplateSourceUrl = item[PnPPartnerPackConstants.PnPProvisioningTemplateSourceUrl] != null ? ((FieldUrlValue)item[PnPPartnerPackConstants.PnPProvisioningTemplateSourceUrl]).Url : null, TemplateFileUri = String.Format("{0}/{1}/{2}", web.Url, PnPPartnerPackConstants.PnPProvisioningTemplates, item.File.Name), TemplateImageUrl = template.ImagePreviewUrl, DisplayName = template.DisplayName, Description = template.Description, }); } } catch (ServerException ex) { // In case of any issue, ignore the local templates } } return(result.ToArray()); }
public ProvisioningJobInformation[] GetProvisioningJobs(ProvisioningJobStatus status, String jobType = null, Boolean includeStream = false, string owner = null) { List <ProvisioningJobInformation> result = new List <ProvisioningJobInformation>(); // Connect to the Infrastructural Site Collection using (var context = PnPPartnerPackContextProvider.GetAppOnlyClientContext(PnPPartnerPackSettings.InfrastructureSiteUrl)) { // Get a reference to the target library Web web = context.Web; List list = web.Lists.GetByTitle(PnPPartnerPackConstants.PnPProvisioningJobs); StringBuilder sbCamlWhere = new StringBuilder(); // Generate the CAML query filter accordingly to the requested statuses Boolean openCamlOr = true; Int32 conditionCounter = 0; foreach (var statusFlagName in Enum.GetNames(typeof(ProvisioningJobStatus))) { var statusFlag = (ProvisioningJobStatus)Enum.Parse(typeof(ProvisioningJobStatus), statusFlagName); if ((statusFlag & status) == statusFlag) { conditionCounter++; if (openCamlOr) { // Add the first <Or /> CAML statement sbCamlWhere.Insert(0, "<Or>"); openCamlOr = false; } sbCamlWhere.AppendFormat( @"<Eq> <FieldRef Name='PnPProvisioningJobStatus' /> <Value Type='Text'>" + statusFlagName + @"</Value> </Eq>"); if (conditionCounter >= 2) { // Close the current <Or /> CAML statement sbCamlWhere.Append("</Or>"); openCamlOr = true; } } } // Remove the first <Or> CAML statement if it is useless if (conditionCounter == 1) { sbCamlWhere.Remove(0, 4); } // Add the jobType filter, if any if (!String.IsNullOrEmpty(jobType)) { sbCamlWhere.Insert(0, "<And>"); sbCamlWhere.AppendFormat( @"<Eq> <FieldRef Name='PnPProvisioningJobType' /> <Value Type='Text'>" + jobType + @"</Value> </Eq>"); sbCamlWhere.Append("</And>"); } // Add the owner filter, if any if (!String.IsNullOrEmpty(owner)) { Microsoft.SharePoint.Client.User ownerUser = web.EnsureUser(owner); context.Load(ownerUser, u => u.Id, u => u.Email, u => u.Title); context.ExecuteQueryRetry(); sbCamlWhere.Insert(0, "<And>"); sbCamlWhere.AppendFormat( @"<Eq> <FieldRef Name='PnPProvisioningJobOwner' /> <Value Type='User'>" + ownerUser.Title + @"</Value> </Eq>"); sbCamlWhere.Append("</And>"); } CamlQuery query = new CamlQuery(); query.ViewXml = @"<View> <Query> <Where>" + sbCamlWhere.ToString() + @" </Where> </Query> </View>"; ListItemCollection items = list.GetItems(query); context.Load(items); context.ExecuteQueryRetry(); foreach (var jobItem in items) { result.Add(PrepareJobInformationFromSharePoint(context, jobItem, includeStream)); } } return(result.ToArray()); }
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)); }
public Guid EnqueueProvisioningJob(ProvisioningJob job) { // Prepare the Job ID Guid jobId = Guid.NewGuid(); // Connect to the Infrastructural Site Collection using (var context = PnPPartnerPackContextProvider.GetAppOnlyClientContext(PnPPartnerPackSettings.InfrastructureSiteUrl)) { // Set the initial status of the Job job.JobId = jobId; job.Status = ProvisioningJobStatus.Pending; // Convert the current Provisioning Job into a Stream Stream stream = job.ToJsonStream(); // Get a reference to the target library Web web = context.Web; List list = web.Lists.GetByTitle(PnPPartnerPackConstants.PnPProvisioningJobs); Microsoft.SharePoint.Client.File file = list.RootFolder.UploadFile(String.Format("{0}.job", jobId), stream, false); Microsoft.SharePoint.Client.User ownerUser = web.EnsureUser(job.Owner); context.Load(ownerUser); context.ExecuteQueryRetry(); ListItem item = file.ListItemAllFields; item[PnPPartnerPackConstants.ContentTypeIdField] = PnPPartnerPackConstants.PnPProvisioningJobContentTypeId; item[PnPPartnerPackConstants.TitleField] = job.Title; item[PnPPartnerPackConstants.PnPProvisioningJobStatus] = ProvisioningJobStatus.Pending.ToString(); item[PnPPartnerPackConstants.PnPProvisioningJobError] = String.Empty; item[PnPPartnerPackConstants.PnPProvisioningJobType] = job.GetType().FullName; FieldUserValue ownerUserValue = new FieldUserValue(); ownerUserValue.LookupId = ownerUser.Id; item[PnPPartnerPackConstants.PnPProvisioningJobOwner] = ownerUserValue; item.Update(); context.ExecuteQueryRetry(); // Check if we need to enqueue a message in the Azure Storage Queue, as well // This happens when the Provisioning Job has to be executed in Continous mode if (PnPPartnerPackSettings.ContinousJobHandlers.ContainsKey(job.GetType())) { // Get the storage account for Azure Storage Queue CloudStorageAccount storageAccount = CloudStorageAccount.Parse(PnPPartnerPackSettings.StorageQueueConnectionString); // Get queue ... and create if it does not exist CloudQueueClient queueClient = storageAccount.CreateCloudQueueClient(); CloudQueue queue = queueClient.GetQueueReference(PnPPartnerPackSettings.StorageQueueName); queue.CreateIfNotExists(); // Add entry to queue ContinousJobItem content = new ContinousJobItem { JobId = job.JobId }; queue.AddMessage(new CloudQueueMessage(JsonConvert.SerializeObject(content))); } } return(jobId); }
private void SaveProvisioningTemplateInternal(ClientContext context, GetProvisioningTemplateJob job, Boolean globalRepository = true) { // Get a reference to the target web site Web web = context.Web; context.Load(web, w => w.Url); context.ExecuteQueryRetry(); // Prepare the support variables ClientContext repositoryContext = null; Web repositoryWeb = null; // Define whether we need to use the global infrastructural repository or the local one if (globalRepository) { // Get a reference to the global repository web site and context repositoryContext = PnPPartnerPackContextProvider.GetAppOnlyClientContext(PnPPartnerPackSettings.InfrastructureSiteUrl); } else { // Get a reference to the local repository web site and context repositoryContext = web.Context.GetSiteCollectionContext(); } using (repositoryContext) { repositoryWeb = repositoryContext.Site.RootWeb; repositoryContext.Load(repositoryWeb, w => w.Url); repositoryContext.ExecuteQueryRetry(); // Configure the XML SharePoint provider for the Infrastructural Site Collection XMLTemplateProvider provider = new XMLSharePointTemplateProvider(repositoryContext, repositoryWeb.Url, PnPPartnerPackConstants.PnPProvisioningTemplates); ProvisioningTemplateCreationInformation ptci = new ProvisioningTemplateCreationInformation(web); ptci.FileConnector = provider.Connector; ptci.IncludeAllTermGroups = job.IncludeAllTermGroups; ptci.IncludeSearchConfiguration = job.IncludeSearchConfiguration; ptci.IncludeSiteCollectionTermGroup = job.IncludeSiteCollectionTermGroup; ptci.IncludeSiteGroups = job.IncludeSiteGroups; ptci.PersistComposedLookFiles = job.PersistComposedLookFiles; // Extract the current template ProvisioningTemplate templateToSave = web.GetProvisioningTemplate(ptci); templateToSave.Description = job.Description; templateToSave.DisplayName = job.Title; // Save template image preview in folder Folder templatesFolder = repositoryWeb.GetFolderByServerRelativeUrl(PnPPartnerPackConstants.PnPProvisioningTemplates); repositoryContext.Load(templatesFolder, f => f.ServerRelativeUrl, f => f.Name); repositoryContext.ExecuteQueryRetry(); // If there is a preview image if (job.TemplateImageFile != null) { String previewImageFileName = job.FileName.Replace(".xml", "_preview.png"); templatesFolder.UploadFile(previewImageFileName, job.TemplateImageFile.ToStream(), true); // And store URL in the XML file templateToSave.ImagePreviewUrl = String.Format("{0}/{1}/{2}", repositoryWeb.Url, templatesFolder.Name, previewImageFileName); } // And save it on the file system provider.SaveAs(templateToSave, job.FileName); Microsoft.SharePoint.Client.File templateFile = templatesFolder.GetFile(job.FileName); ListItem item = templateFile.ListItemAllFields; item[PnPPartnerPackConstants.ContentTypeIdField] = PnPPartnerPackConstants.PnPProvisioningTemplateContentTypeId; item[PnPPartnerPackConstants.TitleField] = job.Title; item[PnPPartnerPackConstants.PnPProvisioningTemplateScope] = job.Scope.ToString(); item[PnPPartnerPackConstants.PnPProvisioningTemplateSourceUrl] = job.SourceSiteUrl; item.Update(); repositoryContext.ExecuteQueryRetry(); } }
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)) { // 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 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 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); // 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) { using (var adminContext = PnPPartnerPackContextProvider.GetAppOnlyTenantLevelClientContext()) { adminContext.RequestTimeout = Timeout.Infinite; // 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; // Use the BaseSiteTemplate of the template, if any, otherwise // fallback to the pre-configured site template (i.e. STS#0) newSite.Template = !String.IsNullOrEmpty(template.BaseSiteTemplate) ? template.BaseSiteTemplate : 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)) { clientContext.RequestTimeout = Timeout.Infinite; 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); // 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 if (job.TemplateParameters != null) { foreach (var key in job.TemplateParameters.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; } // 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 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 SaveProvisioningTemplateInternal(ClientContext context, GetProvisioningTemplateJob job, Boolean globalRepository = true) { // Fix the job filename if it is missing the .pnp extension if (!job.FileName.ToLower().EndsWith(".pnp")) { job.FileName += ".pnp"; } // Get the Access Token from the current context //var accessToken = "Bearer " + context.GetAccessToken(); var accessToken = context.GetAccessToken(); Console.WriteLine("Bearer " + accessToken); // Get a reference to the target web site Web web = context.Web; context.Load(web, w => w.Url, w => w.ServerRelativeUrl); context.ExecuteQueryRetry(); // Prepare the support variables ClientContext repositoryContext = null; Web repositoryWeb = null; // Define whether we need to use the global infrastructural repository or the local one if (globalRepository) { // Get a reference to the global repository web site and context repositoryContext = PnPPartnerPackContextProvider.GetAppOnlyClientContext( PnPPartnerPackSettings.InfrastructureSiteUrl); } else { // Get a reference to the local repository web site and context repositoryContext = web.Context.GetSiteCollectionContext(); } using (repositoryContext) { repositoryWeb = repositoryContext.Site.RootWeb; repositoryContext.Load(repositoryWeb, w => w.Url); repositoryContext.ExecuteQueryRetry(); // Configure the XML SharePoint provider for the Infrastructural Site Collection XMLTemplateProvider provider = new XMLOpenXMLTemplateProvider(job.FileName, new SharePointConnector(repositoryContext, repositoryWeb.Url, PnPPartnerPackConstants.PnPProvisioningTemplates)); ProvisioningTemplateCreationInformation ptci = new ProvisioningTemplateCreationInformation(web); ptci.FileConnector = provider.Connector; ptci.IncludeAllTermGroups = job.IncludeAllTermGroups; ptci.IncludeSearchConfiguration = job.IncludeSearchConfiguration; ptci.IncludeSiteCollectionTermGroup = job.IncludeSiteCollectionTermGroup; ptci.IncludeSiteGroups = job.IncludeSiteGroups; ptci.PersistBrandingFiles = job.PersistComposedLookFiles; // We do intentionally remove taxonomies and search, which are not supported // in the AppOnly Authorization model // For further details, see the PnP Partner Pack documentation ptci.HandlersToProcess ^= Handlers.TermGroups; ptci.HandlersToProcess ^= Handlers.SearchSettings; // Extract the current template ProvisioningTemplate templateToSave = web.GetProvisioningTemplate(ptci); templateToSave.Description = job.Description; templateToSave.DisplayName = job.Title; if (job.PersistComposedLookFiles) { // Create Theme Entity object ThemeEntity themeEntity = web.GetCurrentComposedLook(); foreach (var p in themeEntity.GetType().GetProperties().Where(p => p.GetGetMethod().GetParameters().Count() == 0)) { string propName = p.Name; string propValue = Convert.ToString(p.GetValue(themeEntity, null)); if (propName == "Theme") { propName = "ColorFile"; } else if (propName == "Font") { propName = "FontFile"; } else if (propName == "BackgroundImage") { propValue = "PlaceHolderValue"; } else if (propName == "Name" && String.IsNullOrEmpty(propValue)) { propValue = "CustomTheme"; } string fileName = propValue.Substring(propValue.LastIndexOf("/") + 1); string relativeURL = propValue.Substring(0, propValue.LastIndexOf("/") + 1); // Update template Files if (propName != "Name" && propName != "IsCustomComposedLook" && !String.IsNullOrEmpty(propValue)) { var property = templateToSave.ComposedLook.GetType().GetProperty(propName); try { string folderPath = ""; Stream fileStream = null; if (propName == "BackgroundImage") { if (job.templateBackgroundImgFile != null) { folderPath = "{site}/SiteAssets"; fileName = job.FileName.ToLower().Replace(".pnp", ".png"); fileStream = job.templateBackgroundImgFile.ToStream(); Console.WriteLine("fileName: " + fileName); Console.WriteLine("fileStream: " + fileStream); templateToSave.ComposedLook.BackgroundFile = String.Format("{{sitecollection}}/SiteAssets/{0}", fileName); } } else if (propName.Contains("MasterPage")) { folderPath = "{masterpagecatalog}"; var strUrl = String.Format("{0}/_api/web/getfilebyserverrelativeurl('{1}{2}')/$value", web.Url, web.ServerRelativeUrl, propValue); fileStream = HttpHelper.MakeGetRequestForStream(strUrl, "application/octet-stream", accessToken); property.SetValue(templateToSave.ComposedLook, String.Format("{{masterpagecatalog}}/{0}", fileName), new object[] { }); } else { folderPath = "{themecatalog}/15"; var strUrl = String.Format("{0}/_api/web/getfilebyserverrelativeurl('{1}{2}')/$value", web.Url, web.ServerRelativeUrl, propValue); fileStream = HttpHelper.MakeGetRequestForStream(strUrl, "application/octet-stream", accessToken); property.SetValue(templateToSave.ComposedLook, String.Format("{{themecatalog}}/15/{0}", fileName), new object[] { }); } Console.WriteLine("Saving files: {0}, {1}", fileName, fileStream); provider.Connector.SaveFileStream(fileName, fileStream); Console.WriteLine("File Paths: {0}, {1}", fileName, folderPath); templateToSave.Files.Add(new OfficeDevPnP.Core.Framework.Provisioning.Model.File { Src = fileName, Folder = folderPath, Overwrite = true, }); Console.WriteLine("Files saved: {0}, {1}", fileName, folderPath); } catch (Exception ex) { Console.WriteLine(ex); } } else if (propName == "Name") { var property = templateToSave.ComposedLook.GetType().GetProperty(propName); property.SetValue(templateToSave.ComposedLook, fileName, new object[] { }); } } if (job.templateAltCSSFile != null) { //TODO: Add handling for native Alternate CSS //web.AlternateCssUrl; string folderPath = "{site}/SiteAssets"; string fileName = job.FileName.ToLower().Replace(".pnp", ".css"); Stream fileStream = job.templateAltCSSFile.ToStream(); provider.Connector.SaveFileStream(fileName, fileStream); templateToSave.WebSettings = new WebSettings { AlternateCSS = String.Format("{{sitecollection}}/SiteAssets/{0}", fileName), }; Console.WriteLine("File Paths: {0}, {1}", fileName, folderPath); templateToSave.Files.Add(new OfficeDevPnP.Core.Framework.Provisioning.Model.File { Src = fileName, Folder = folderPath, Overwrite = true, }); } } // Save template image preview in folder Microsoft.SharePoint.Client.Folder templatesFolder = repositoryWeb.GetFolderByServerRelativeUrl(PnPPartnerPackConstants.PnPProvisioningTemplates); repositoryContext.Load(templatesFolder, f => f.ServerRelativeUrl, f => f.Name); repositoryContext.ExecuteQueryRetry(); // If there is a preview image if (job.TemplateImageFile != null) { // Determine the preview image file name String previewImageFileName = job.FileName.ToLower().Replace(".pnp", "_preview.png"); // Save the preview image inside the Open XML package provider.Connector.SaveFileStream(previewImageFileName, job.TemplateImageFile.ToStream()); // And store URL in the XML file templateToSave.ImagePreviewUrl = String.Format("{0}{1}/{2}/{3}/{4}", repositoryWeb.Url.ToLower().StartsWith("https") ? "pnps" : "pnp", repositoryWeb.Url.Substring(repositoryWeb.Url.IndexOf("://")), templatesFolder.Name, job.FileName, previewImageFileName); } // And save it on the file system provider.SaveAs(templateToSave, job.FileName.ToLower().Replace(".pnp", ".xml")); Microsoft.SharePoint.Client.File templateFile = templatesFolder.GetFile(job.FileName); ListItem item = templateFile.ListItemAllFields; item[PnPPartnerPackConstants.ContentTypeIdField] = PnPPartnerPackConstants.PnPProvisioningTemplateContentTypeId; item[PnPPartnerPackConstants.TitleField] = job.Title; item[PnPPartnerPackConstants.PnPProvisioningTemplateScope] = job.Scope.ToString(); item[PnPPartnerPackConstants.PnPProvisioningTemplateSourceUrl] = job.SourceSiteUrl; item.Update(); repositoryContext.ExecuteQueryRetry(); } }
private void SaveProvisioningTemplateInternal(ClientContext context, GetProvisioningTemplateJob job, Boolean globalRepository = true) { // Fix the job filename if it is missing the .pnp extension if (!job.FileName.ToLower().EndsWith(".pnp")) { job.FileName += ".pnp"; } // Get a reference to the target web site Web web = context.Web; context.Load(web, w => w.Url); context.ExecuteQueryRetry(); // Prepare the support variables ClientContext repositoryContext = null; Web repositoryWeb = null; // Define whether we need to use the global infrastructural repository or the local one if (globalRepository) { // Get a reference to the global repository web site and context repositoryContext = PnPPartnerPackContextProvider.GetAppOnlyClientContext( PnPPartnerPackSettings.InfrastructureSiteUrl); } else { // Get a reference to the local repository web site and context repositoryContext = web.Context.GetSiteCollectionContext(); } using (repositoryContext) { repositoryWeb = repositoryContext.Site.RootWeb; repositoryContext.Load(repositoryWeb, w => w.Url); repositoryContext.ExecuteQueryRetry(); // Configure the XML SharePoint provider for the Infrastructural Site Collection XMLTemplateProvider provider = new XMLOpenXMLTemplateProvider(job.FileName, new SharePointConnector(repositoryContext, repositoryWeb.Url, PnPPartnerPackConstants.PnPProvisioningTemplates)); ProvisioningTemplateCreationInformation ptci = new ProvisioningTemplateCreationInformation(web); ptci.FileConnector = provider.Connector; ptci.IncludeAllTermGroups = job.IncludeAllTermGroups; ptci.IncludeSearchConfiguration = job.IncludeSearchConfiguration; ptci.IncludeSiteCollectionTermGroup = job.IncludeSiteCollectionTermGroup; ptci.IncludeSiteGroups = job.IncludeSiteGroups; ptci.PersistBrandingFiles = job.PersistComposedLookFiles; // We do intentionally remove taxonomies and search, which are not supported // in the AppOnly Authorization model // For further details, see the PnP Partner Pack documentation ptci.HandlersToProcess ^= Handlers.TermGroups; ptci.HandlersToProcess ^= Handlers.SearchSettings; // Extract the current template ProvisioningTemplate templateToSave = web.GetProvisioningTemplate(ptci); templateToSave.Description = job.Description; templateToSave.DisplayName = job.Title; // Save template image preview in folder Microsoft.SharePoint.Client.Folder templatesFolder = repositoryWeb.GetFolderByServerRelativeUrl(PnPPartnerPackConstants.PnPProvisioningTemplates); repositoryContext.Load(templatesFolder, f => f.ServerRelativeUrl, f => f.Name); repositoryContext.ExecuteQueryRetry(); // If there is a preview image if (job.TemplateImageFile != null) { // Determine the preview image file name String previewImageFileName = job.FileName.ToLower().Replace(".pnp", "_preview.png"); // Save the preview image inside the Open XML package provider.Connector.SaveFileStream(previewImageFileName, job.TemplateImageFile.ToStream()); // And store URL in the XML file templateToSave.ImagePreviewUrl = String.Format("{0}{1}/{2}/{3}/{4}", repositoryWeb.Url.ToLower().StartsWith("https") ? "pnps" : "pnp", repositoryWeb.Url.Substring(repositoryWeb.Url.IndexOf("://")), templatesFolder.Name, job.FileName, previewImageFileName); } // And save it on the file system provider.SaveAs(templateToSave, job.FileName.ToLower().Replace(".pnp", ".xml")); Microsoft.SharePoint.Client.File templateFile = templatesFolder.GetFile(job.FileName); ListItem item = templateFile.ListItemAllFields; item[PnPPartnerPackConstants.ContentTypeIdField] = PnPPartnerPackConstants.PnPProvisioningTemplateContentTypeId; item[PnPPartnerPackConstants.TitleField] = job.Title; item[PnPPartnerPackConstants.PnPProvisioningTemplateScope] = job.Scope.ToString(); item[PnPPartnerPackConstants.PnPProvisioningTemplateSourceUrl] = job.SourceSiteUrl; item.Update(); repositoryContext.ExecuteQueryRetry(); } }