private static void CreateContentRecursive(Content sourceContent, Node targetContainer) { var sourceNode = sourceContent.ContentHandler; var alreadyExisting = Node.LoadNode(targetContainer.Path + "/" + sourceNode.Name); if (alreadyExisting != null && alreadyExisting.NodeType.Name != sourceNode.NodeType.Name) { throw new Exception("The target node already exists with a different type."); } var target = alreadyExisting ?? NodeType.CreateInstance(sourceNode.NodeType.Name, targetContainer); target.Name = sourceNode.Name; target.DisplayName = sourceNode.DisplayName; target.Index = sourceNode.Index; target.NodeOperation = NodeOperation.TemplateChildCopy; var targetContent = Content.Create(target); // We do not want to set the current user here but the user we 'inherited' // from the parent (the template). In case of user profiles (my site) the // creator and the owner will be the user itself. var realCreatorUser = targetContainer.CreatedBy; var realModifierUser = targetContainer.ModifiedBy; var now = DateTime.UtcNow; target.CreatedBy = realCreatorUser; target.VersionCreatedBy = realCreatorUser; target.ModificationDate = now; target.ModifiedBy = realModifierUser; target.VersionModificationDate = now; target.VersionModifiedBy = realModifierUser; target.Owner = realCreatorUser; foreach (var propertyType in sourceNode.PropertyTypes.Where(pt => !pt.IsContentListProperty)) { switch (propertyType.DataType) { case DataType.Binary: var sourceBinaryData = sourceNode.GetBinary(propertyType); var targetBinaryData = new BinaryData(); targetBinaryData.CopyFrom(sourceBinaryData); target.SetBinary(propertyType.Name, targetBinaryData); break; default: target[propertyType] = sourceNode[propertyType]; break; } } // Iterate through content list fields and set their value on the target node separately. // This is needed because the same content list fields may have a different property name // (e.g. #String_0 and #String_1) in the source and target content lists. foreach (var field in sourceContent.Fields.Values.Where(f => f.Name.StartsWith("#"))) { // this should give us the name of the source property (e.g. #String_0) var sourcePropertyName = field.FieldSetting.Bindings.FirstOrDefault(); if (string.IsNullOrEmpty(sourcePropertyName)) { continue; } // this should give us the name of the target property (e.g. #String_1) var targetPropertyName = targetContent.Fields[field.Name].FieldSetting.Bindings.FirstOrDefault(); if (string.IsNullOrEmpty(targetPropertyName)) { continue; } if (field is BinaryField) { var sourceBinaryData = sourceNode.GetBinary(sourcePropertyName); var targetBinaryData = new BinaryData(); targetBinaryData.CopyFrom(sourceBinaryData); target.SetBinary(targetPropertyName, targetBinaryData); } else { target[targetPropertyName] = sourceNode[sourcePropertyName]; } } // workaround for content lists: content list type needs to be refreshed var contentList = target as ContentList; if (contentList != null) { contentList.ContentListDefinition = contentList.ContentListDefinition; } target.Save(); // inherit explicit permissions from template using (new SystemAccount()) { var entries = SecurityHandler.GetExplicitEntriesAsSystemUser(sourceNode.Id, null, EntryType.Normal); if (entries.Count > 0) { var aclEdit = SecurityHandler.CreateAclEditor(); foreach (var ace in entries) { aclEdit.SetEntry(target.Id, ace, true); } aclEdit.Apply(); } } // This is to make sure that only those children are copied // that are really under this content. E.g. SmartFolder may // contain real children and queried children too. foreach (var childNode in sourceNode.PhysicalChildArray.Where(ch => ch.InFolder(sourceNode.Path))) { CreateContentRecursive(Content.Create(childNode), target); } }