public void CanProvisionObjects() { var template = new ProvisioningTemplate(); var listInstance = new Core.Framework.Provisioning.Model.ListInstance(); listInstance.Url = string.Format("lists/{0}", listName); listInstance.Title = listName; listInstance.TemplateType = (int) ListTemplateType.GenericList; Dictionary<string, string> dataValues = new Dictionary<string, string>(); dataValues.Add("Title","Test"); DataRow dataRow = new DataRow(dataValues); listInstance.DataRows.Add(dataRow); template.Lists.Add(listInstance); using (var ctx = TestCommon.CreateClientContext()) { TokenParser.Initialize(ctx.Web, template); new ObjectListInstance().ProvisionObjects(ctx.Web, template); var list = ctx.Web.GetListByUrl(listInstance.Url); Assert.IsNotNull(list); var items = list.GetItems(CamlQuery.CreateAllItemsQuery()); ctx.Load(items, itms => itms.Include(item => item["Title"])); ctx.ExecuteQueryRetry(); Assert.IsTrue(items.Count == 1); Assert.IsTrue(items[0]["Title"].ToString() == "Test"); } }
public ListItem CreateListItem(DataRow dataRow, ProvisioningTemplate template) { ListItem listitem = null; string dir = null; string dirValue; if (dataRow.Values.TryGetValue(FIELD_ItemDir, out dirValue) && !string.IsNullOrEmpty(dirValue)) { dir = TokenParser.CombineUrl(m_listServerRelativeUrl, dirValue); } string objType; if (!dataRow.Values.TryGetValue(FIELD_ItemType, out objType)) { objType = ""; } switch (objType) { case FIELD_ItemType_FolderValue: { string name; if (dataRow.Values.TryGetValue(FIELD_ItemName, out name)) { ListItemCreationInformation creationInfo = new ListItemCreationInformation() { UnderlyingObjectType = FileSystemObjectType.Folder, LeafName = name, FolderUrl = dir }; listitem = this.List.AddItem(creationInfo); } break; } case FIELD_ItemType_FileValue: { string name; if (dataRow.Values.TryGetValue(FIELD_ItemName, out name) && !string.IsNullOrEmpty(dataRow.FileSrc)) { if (string.IsNullOrEmpty(dir)) { dir = this.List.RootFolder.ServerRelativeUrl; } FileCreationInformation creationInfo = new FileCreationInformation() { Overwrite = true, ContentStream = template.Connector.GetFileStream(dataRow.FileSrc), Url = TokenParser.CombineUrl(dir, name) }; var newFile = this.List.RootFolder.Files.Add(creationInfo); listitem = newFile.ListItemAllFields; } break; } default: { ListItemCreationInformation creationInfo = new ListItemCreationInformation() { FolderUrl = dir }; listitem = this.List.AddItem(creationInfo); break; } } return listitem; }
private void AddIDMappingEntry(ListItem item, DataRow dataRow) { int oldId; string strId; if (dataRow.Values.TryGetValue("ID", out strId) && int.TryParse(strId, out oldId) && (0 < oldId)) { if (null == m_mappingIDs) { m_mappingIDs = new Dictionary<int, int>(); } m_mappingIDs[oldId] = item.Id; } }
public List<DataRow> ExtractItems( ProvisioningTemplateCreationInformation creationInfo, TokenParser parser, PnPMonitoredScope scope) { List<DataRow> dataRows = new List<DataRow>(); bool isPageLib = (List.BaseTemplate == (int)ListTemplateType.WebPageLibrary) || (List.BaseTemplate == (int)ListTemplateType.HomePageLibrary) || (List.BaseTemplate == (int)ListTemplateType.PublishingPages); CamlQuery query = isPageLib ? CamlQuery.CreateAllFoldersQuery() : CamlQuery.CreateAllItemsQuery(); query.DatesInUtc = true; ListItemCollection items = this.List.GetItems(query); this.Context.Load(items, col => col.IncludeWithDefaultProperties(i => i.HasUniqueRoleAssignments)); this.Context.Load(this.List.Fields); this.Context.Load(this.List, l=> l.RootFolder.ServerRelativeUrl, l=> l.BaseType); this.Context.ExecuteQueryRetry(); ItemPathProvider itemPathProvider = new ItemPathProvider(this.List, this.Web); List<Field> fields = GetListContentSerializableFields(true); foreach (ListItem item in items) { try { Dictionary<string, string> values = new Dictionary<string, string>(); foreach (Field field in fields) { if (CanFieldContentBeIncluded(field, true)) { string str = ""; object value = null; ; try { value = item[field.InternalName]; } catch (Exception ex) { scope.LogWarning(ex, "Failed to read item field value. List:{0}, Item ID:{1}, Field: {2}", this.List.Title, item.Id, field.InternalName); } if (null != value) { try { FieldValueProvider provider = GetFieldValueProvider(field, this.Web); str = provider.GetValidatedValue(value); } catch (Exception ex) { scope.LogWarning(ex, "Failed to serialize item field value. List:{0}, Item ID:{1}, Field: {2}", this.List.Title, item.Id, field.InternalName); } if (!string.IsNullOrEmpty(str)) { values.Add(field.InternalName, str); } } } } string fileSrc; itemPathProvider.ExtractItemPathValues(item, values, creationInfo, out fileSrc); if (values.Any()) { ObjectSecurity security = null; if (item.HasUniqueRoleAssignments) { try { security = item.GetSecurity(parser); security.ClearSubscopes = true; } catch (Exception ex) { scope.LogWarning(ex, "Failed to get item security. Item ID: {0}, List: '{1}'.", item.Id, this.List.Title); } } DataRow row = new DataRow(values, security, fileSrc); dataRows.Add(row); } } catch (Exception ex) { scope.LogError(ex, "Failed to save item in template. Item ID: {0}, List: '{1}'.", item.Id, this.List.Title); } } return dataRows; }
internal override void OverrideXmlData(XElement sourceObject, XElement targetObject) { XNamespace ns = SchemaVersion; #region Property handling // Base property handling // Drop list properties if they're not provided in the source XML string[] ListProperties = new string[] { "Description", "DocumentTemplate", "MinorVersionLimit", "MaxVersionLimit", "DraftVersionVisibility", "TemplateFeatureID", "EnableAttachments" }; foreach (string listProperty in ListProperties) { if (sourceObject.Attribute(listProperty) == null) { DropAttribute(targetObject, listProperty); } } // Drop list elements if they're not provided in the source XML string[] ListElements = new string[] { "ContentTypeBindings", "Views", "FieldRefs", "Fields" }; foreach (var listElement in ListElements) { var sourceListElementXML = sourceObject.Descendants(ns + listElement); var targetListElementXML = targetObject.Descendants(ns + listElement); if (sourceListElementXML.Any() == false && targetListElementXML.Any() == true) { targetListElementXML.Remove(); } } #if ONPREMISES // MaxVersionLimit cannot be set in on-premises, so remove it before comparing before and after if (sourceObject.Attribute("MaxVersionLimit") != null) { DropAttribute(targetObject, "MaxVersionLimit"); DropAttribute(sourceObject, "MaxVersionLimit"); } #endif #endregion #region Contenttype handling // If RemoveExistingContentTypes is set then remove the attribute from source since on target we don't add this. var contentTypeBindings = targetObject.Descendants(ns + "ContentTypeBinding"); bool removeExistingContentTypes = false; if (sourceObject.Attribute("RemoveExistingContentTypes") != null) { removeExistingContentTypes = sourceObject.Attribute("RemoveExistingContentTypes").Value.ToBoolean(); DropAttribute(sourceObject, "RemoveExistingContentTypes"); } if (contentTypeBindings != null && contentTypeBindings.Any()) { // One can add ContentTypeBindings without specifying ContentTypesEnabled. The engine will turn on ContentTypesEnabled automatically in that case if (sourceObject.Attribute("ContentTypesEnabled") == null) { DropAttribute(targetObject, "ContentTypesEnabled"); } if (removeExistingContentTypes) { foreach (var contentTypeBinding in contentTypeBindings.ToList()) { // Remove the folder content type if present because we're not removing that one via RemoveExistingContentTypes if (contentTypeBinding.Attribute("ContentTypeID").Value == "0x0120") { contentTypeBinding.Remove(); } } } else // We did not remove existing content types { var sourceContentTypeBindings = sourceObject.Descendants(ns + "ContentTypeBinding"); foreach (var contentTypeBinding in contentTypeBindings.ToList()) { string value = contentTypeBinding.Attribute("ContentTypeID").Value; // drop all content types which are not mentioned in the source if (sourceContentTypeBindings.Where(p => p.Attribute("ContentTypeID").Value == value).Any() == false) { contentTypeBinding.Remove(); } } } } #endregion #region FieldRef handling var fieldRefs = sourceObject.Descendants(ns + "FieldRef"); if (fieldRefs != null && fieldRefs.Any()) { foreach (var fieldRef in fieldRefs.ToList()) { // Drop the name attribute from the source fieldrefs since this is just an informational attribute if (fieldRef.Attribute("Name") != null) { DropAttribute(fieldRef, "Name"); } // Drop hidden fieldrefs since they're not retreived by the engine again if (fieldRef.Attribute("Hidden") != null && fieldRef.Attribute("Hidden").Value.ToBoolean() == true) { fieldRef.Remove(); } } } var targetFieldRefs = targetObject.Descendants(ns + "FieldRef"); if (targetFieldRefs != null && targetFieldRefs.Any()) { foreach (var targetFieldRef in targetFieldRefs.ToList()) { // Drop the name attribute from the source fieldrefs since this is just an informational attribute if (targetFieldRef.Attribute("Name") != null) { DropAttribute(targetFieldRef, "Name"); } // Drop the fields which were not present in source (there's always some OOB fieldrefs) if (!fieldRefs.Where(p => p.Attribute("ID").Value == targetFieldRef.Attribute("ID").Value).Any()) { targetFieldRef.Remove(); } else { // If the source object does not have a DisplayName attribute then also remove it from the target if (!(fieldRefs.Where(p => p.Attribute("ID").Value == targetFieldRef.Attribute("ID").Value).FirstOrDefault().Attribute("DisplayName") != null)) { DropAttribute(targetFieldRef, "DisplayName"); } } } } #endregion #region Field handling var targetFields = targetObject.Descendants("Field"); var sourceFields = sourceObject.Descendants("Field"); if (sourceFields != null && sourceFields.Any()) { foreach (var sourceField in sourceFields.ToList()) { // Ensure both target and source using the same casing UpperCaseAttribute(sourceField, "ID"); } } if (targetFields != null && targetFields.Any()) { foreach (var targetField in targetFields.ToList()) { // Ensure both target and source using the same casing UpperCaseAttribute(targetField, "ID"); // Drop attributes before comparison DropAttribute(targetField, "SourceID"); DropAttribute(targetField, "StaticName"); DropAttribute(targetField, "ColName"); DropAttribute(targetField, "RowOrdinal"); DropAttribute(targetField, "Version"); // If target field does not exist in source then drop it (SPO can add additional fields e.g. _IsRecord field refering the _ComplianceFlags field) if (sourceFields != null && sourceFields.Any()) { if (!sourceFields.Where(p => p.Attribute("ID").Value.Equals(targetField.Attribute("ID").Value)).Any()) { targetField.Remove(); } } } } #endregion #region View handling var sourceViews = sourceObject.Descendants("View"); var targetViews = targetObject.Descendants("View"); if (sourceViews != null && sourceViews.Any()) { int sourceViewCount = 0; int targetViewCount = 0; foreach (var sourceView in sourceViews) { sourceViewCount++; string sourceViewName = sourceView.Attribute("DisplayName").Value; if (targetViews.Where(v => v.Attribute("DisplayName").Value.Equals(sourceViewName, StringComparison.InvariantCultureIgnoreCase)).First() != null) { targetViewCount++; } } if (sourceViewCount == targetViewCount) { // if RemoveExistingViews was checked then we should have the same count of source and target views if (sourceObject.Descendants(ns + "Views").First().Attribute("RemoveExistingViews") != null && sourceObject.Descendants(ns + "Views").First().Attribute("RemoveExistingViews").Value.ToBoolean() == true) { if (sourceViews.Count() == targetViews.Count()) { // we've found the source views in the target + the original views were dropped, so we're good. Drop the view element to ensure valid XML comparison sourceObject.Descendants(ns + "Views").Remove(); targetObject.Descendants(ns + "Views").Remove(); } } else { // we've found the source views in the target so we're good. Drop the view element to ensure valid XML comparison sourceObject.Descendants(ns + "Views").Remove(); targetObject.Descendants(ns + "Views").Remove(); } } } #endregion #region FieldDefaults handling var sourceFieldDefaults = sourceObject.Descendants(ns + "FieldDefault"); if (sourceFieldDefaults != null && sourceFieldDefaults.Any()) { bool validFieldDefaults = true; foreach(var sourceFieldDefault in sourceFieldDefaults) { string fieldDefaultValue = sourceFieldDefault.Value; string fieldDefaultName = sourceFieldDefault.Attribute("FieldName").Value; if (fieldDefaultValue != null && fieldDefaultName != null) { var targetField = targetFields.Where(p => p.Attribute("Name").Value.Equals(fieldDefaultName, StringComparison.InvariantCultureIgnoreCase)).First(); if (targetField.Descendants("Default").Any()) { string targetFieldDefaultValue = targetField.Descendants("Default").First().Value; if (!targetFieldDefaultValue.Equals(fieldDefaultValue, StringComparison.InvariantCultureIgnoreCase)) { validFieldDefaults = false; } else { // remove the Default node targetField.Descendants("Default").First().Remove(); } } else { validFieldDefaults = false; } } } if (validFieldDefaults) { sourceObject.Descendants(ns + "FieldDefaults").Remove(); } } // Drop any remaining Default node foreach (var targetField in targetFields) { if (targetField.Descendants("Default").Any()) { targetField.Descendants("Default").First().Remove(); } } #endregion #region Folder handling // Folders are not extracted, so manual validation needed var sourceFolders = sourceObject.Descendants(ns + "Folders"); if (sourceFolders != null && sourceFolders.Any()) { // use CSOM to verify the folders are listed in target and only remove the source folder from the XML when this is the case if (this.cc != null) { var foldersValid = true; var list = this.cc.Web.GetListByUrl(sourceObject.Attribute("Url").Value); if (list != null) { list.EnsureProperty(w => w.RootFolder); foreach(var folder in sourceFolders.Descendants(ns + "Folder")) { // only verify first level folders if (folder.Parent.Equals(sourceFolders.First())) { if (!list.RootFolder.FolderExists(folder.Attribute("Name").Value)) { foldersValid = false; } // if the folder has a security element then verify this as well var sourceFolderSecurity = folder.Descendants(ns + "Security"); if (sourceFolderSecurity != null && sourceFolderSecurity.Any()) { // convert XML in ObjectSecurity object ObjectSecurity sourceFolderSecurityElement = new ObjectSecurity(); sourceFolderSecurityElement.ClearSubscopes = sourceFolderSecurity.Descendants(ns + "BreakRoleInheritance").First().Attribute("ClearSubscopes").Value.ToBoolean(); sourceFolderSecurityElement.CopyRoleAssignments = sourceFolderSecurity.Descendants(ns + "BreakRoleInheritance").First().Attribute("CopyRoleAssignments").Value.ToBoolean(); var sourceRoleAssignments = folder.Descendants(ns + "RoleAssignment"); foreach (var sourceRoleAssignment in sourceRoleAssignments) { sourceFolderSecurityElement.RoleAssignments.Add(new Core.Framework.Provisioning.Model.RoleAssignment() { Principal = sourceRoleAssignment.Attribute("Principal").Value, RoleDefinition = sourceRoleAssignment.Attribute("RoleDefinition").Value }); } // grab the "Securable" for the folder var currentFolderItem = list.RootFolder.EnsureFolder(folder.Attribute("Name").Value).ListItemAllFields; cc.Load(currentFolderItem); cc.ExecuteQueryRetry(); // use CSOM to verify security settings if (ValidateSecurityCSOM(this.cc, sourceFolderSecurityElement, currentFolderItem)) { sourceFolderSecurity.Remove(); } } } } } if (foldersValid) { sourceFolders.Remove(); } } } #endregion #region DataRows handling var sourceDataRows = sourceObject.Descendants(ns + "DataRow"); if (sourceDataRows != null && sourceDataRows.Any()) { bool dataRowsValidated = true; var list = this.cc.Web.GetListByUrl(sourceObject.Attribute("Url").Value); if (list != null) { int dataRowCount = 0; foreach (var sourceDataRow in sourceDataRows) { // Convert XML in DataRow object DataRow sourceDataRowElement = null; Dictionary<string, string> values = new Dictionary<string, string>(); foreach (var dataValue in sourceDataRow.Descendants(ns + "DataValue")) { values.Add(dataValue.Attribute("FieldName").Value, dataValue.Value); } ObjectSecurity sourceDataRowSecurityElement = null; var sourceDataRowSecurity = sourceDataRow.Descendants(ns + "Security"); if (sourceDataRowSecurity != null && sourceDataRowSecurity.Any()) { // convert XML in ObjectSecurity object sourceDataRowSecurityElement = new ObjectSecurity(); sourceDataRowSecurityElement.ClearSubscopes = sourceDataRowSecurity.Descendants(ns + "BreakRoleInheritance").First().Attribute("ClearSubscopes").Value.ToBoolean(); sourceDataRowSecurityElement.CopyRoleAssignments = sourceDataRowSecurity.Descendants(ns + "BreakRoleInheritance").First().Attribute("CopyRoleAssignments").Value.ToBoolean(); var sourceRoleAssignments = sourceDataRowSecurity.Descendants(ns + "RoleAssignment"); foreach (var sourceRoleAssignment in sourceRoleAssignments) { sourceDataRowSecurityElement.RoleAssignments.Add(new Core.Framework.Provisioning.Model.RoleAssignment() { Principal = sourceRoleAssignment.Attribute("Principal").Value, RoleDefinition = sourceRoleAssignment.Attribute("RoleDefinition").Value }); } } if (sourceDataRowSecurityElement != null) { sourceDataRowElement = new DataRow(values, sourceDataRowSecurityElement); } else { sourceDataRowElement = new DataRow(values); } dataRowCount++; ListItem itemToValidate = null; try { itemToValidate = list.GetItemById(dataRowCount); } catch { } if (itemToValidate == null || !ValidateDataRowsCSOM(cc, sourceDataRowElement, itemToValidate)) { dataRowsValidated = false; } } } // If all datarows are validated then we can drop if (dataRowsValidated) { sourceObject.Descendants(ns + "DataRows").First().Remove(); } } #endregion #region Security handling var sourceSecurity = sourceObject.Descendants(ns + "Security"); if (sourceSecurity != null && sourceSecurity.Any()) { var targetSecurity = targetObject.Descendants(ns + "Security"); if (ValidateSecurityXml(sourceSecurity.First(), targetSecurity.First())) { sourceSecurity.Remove(); targetSecurity.Remove(); } } #endregion #region CustomAction handling var sourceCustomActions = sourceObject.Descendants(ns + "UserCustomActions"); if (sourceCustomActions != null && sourceCustomActions.Any()) { // delete custom actions since we validate these latter on var targetCustomActions = targetObject.Descendants(ns + "UserCustomActions"); sourceCustomActions.Remove(); if (targetCustomActions != null && targetCustomActions.Any()) { targetCustomActions.Remove(); } } #endregion }