diff --git a/src/Umbraco.Core/Models/Content.cs b/src/Umbraco.Core/Models/Content.cs
index fefbdfbef7..92b0488a82 100644
--- a/src/Umbraco.Core/Models/Content.cs
+++ b/src/Umbraco.Core/Models/Content.cs
@@ -438,6 +438,7 @@ namespace Umbraco.Core.Models
_contentType = contentType;
ContentTypeBase = contentType;
Properties.EnsurePropertyTypes(PropertyTypes);
+ //TODO: Shouldn't we remove this event handler first before re-adding it in case the handler already exists
Properties.CollectionChanged += PropertiesChanged;
}
@@ -455,6 +456,7 @@ namespace Umbraco.Core.Models
_contentType = contentType;
ContentTypeBase = contentType;
Properties.EnsureCleanPropertyTypes(PropertyTypes);
+ //TODO: Shouldn't we remove this event handler first before re-adding it in case the handler already exists
Properties.CollectionChanged += PropertiesChanged;
return;
}
@@ -500,10 +502,18 @@ namespace Umbraco.Core.Models
public override object DeepClone()
{
var clone = (Content) base.DeepClone();
+
//turn off change tracking
clone.DisableChangeTracking();
- //need to manually clone this since it's not settable
- clone._contentType = (IContentType)ContentType.DeepClone();
+
+ //if culture infos exist then deal with event bindings
+ if (clone._publishInfos != null)
+ {
+ clone._publishInfos.CollectionChanged -= this.PublishNamesCollectionChanged; //clear this event handler if any
+ clone._publishInfos = (CultureNameCollection)_publishInfos.DeepClone(); //manually deep clone
+ clone._publishInfos.CollectionChanged += clone.PublishNamesCollectionChanged; //re-assign correct event handler
+ }
+
//this shouldn't really be needed since we're not tracking
clone.ResetDirtyProperties(false);
//re-enable tracking
diff --git a/src/Umbraco.Core/Models/ContentBase.cs b/src/Umbraco.Core/Models/ContentBase.cs
index 2336188c50..1c5ee18be6 100644
--- a/src/Umbraco.Core/Models/ContentBase.cs
+++ b/src/Umbraco.Core/Models/ContentBase.cs
@@ -113,7 +113,11 @@ namespace Umbraco.Core.Models
///
/// Gets or sets the collection of properties for the entity.
///
+ ///
+ /// Marked DoNotClone since we'll manually clone the underlying field to deal with the event handling
+ ///
[DataMember]
+ [DoNotClone]
public virtual PropertyCollection Properties
{
get => _properties;
@@ -477,5 +481,39 @@ namespace Umbraco.Core.Models
}
#endregion
+
+ ///
+ /// Override to deal with specific object instances
+ ///
+ ///
+ public override object DeepClone()
+ {
+ var clone = (ContentBase)base.DeepClone();
+ //turn off change tracking
+ clone.DisableChangeTracking();
+
+ //if culture infos exist then deal with event bindings
+ if (clone._cultureInfos != null)
+ {
+ clone._cultureInfos.CollectionChanged -= this.CultureNamesCollectionChanged; //clear this event handler if any
+ clone._cultureInfos = (CultureNameCollection)_cultureInfos.DeepClone(); //manually deep clone
+ clone._cultureInfos.CollectionChanged += clone.CultureNamesCollectionChanged; //re-assign correct event handler
+ }
+
+ //if properties exist then deal with event bindings
+ if (clone._properties != null)
+ {
+ clone._properties.CollectionChanged -= this.PropertiesChanged; //clear this event handler if any
+ clone._properties = (PropertyCollection)_properties.DeepClone(); //manually deep clone
+ clone._properties.CollectionChanged += clone.PropertiesChanged; //re-assign correct event handler
+ }
+
+ //this shouldn't really be needed since we're not tracking
+ clone.ResetDirtyProperties(false);
+ //re-enable tracking
+ clone.EnableChangeTracking();
+
+ return clone;
+ }
}
}
diff --git a/src/Umbraco.Core/Models/Entities/EntityBase.cs b/src/Umbraco.Core/Models/Entities/EntityBase.cs
index ab57d57ab6..9cd6d1edad 100644
--- a/src/Umbraco.Core/Models/Entities/EntityBase.cs
+++ b/src/Umbraco.Core/Models/Entities/EntityBase.cs
@@ -13,6 +13,10 @@ namespace Umbraco.Core.Models.Entities
[DebuggerDisplay("Id: {" + nameof(Id) + "}")]
public abstract class EntityBase : BeingDirtyBase, IEntity
{
+#if DEBUG
+ public Guid InstanceId = Guid.NewGuid();
+#endif
+
private static readonly Lazy Ps = new Lazy();
private bool _hasIdentity;
@@ -161,6 +165,11 @@ namespace Umbraco.Core.Models.Entities
var unused = Key; // ensure that 'this' has a key, before cloning
var clone = (EntityBase) MemberwiseClone();
+#if DEBUG
+ clone.InstanceId = Guid.NewGuid();
+#endif
+
+
// clear changes (ensures the clone has its own dictionaries)
// then disable change tracking
clone.ResetDirtyProperties(false);