This article addresses a technical challenge in Sitecore 9.x regarding facet management on xConnect contacts. In the earlier 8.2 version, developers could use a .Reset() extension method to clear facets, but this functionality was removed in 9.x.

The Problem

When attempting to replace an existing facet with a new instance, developers encounter the error “Facet already exists on the contact.” This occurs because xConnect tracks facets using a ConcurrencyToken to maintain data integrity and prevent unauthorized overwrites.

The Solution

Rather than manually resetting each property to its default value, I created a custom extension method. The extension creates a fresh facet instance while preserving the original ConcurrencyToken through reflection:

public static T GetFacetWithDefaultValues<T>(this T facet) where T : Facet, new()
{
    var newFacet = new T();
    var concurrencyTokenProperty = typeof(Facet).GetProperty("ConcurrencyToken");
    var originalToken = concurrencyTokenProperty.GetValue(facet);
    concurrencyTokenProperty.SetValue(newFacet, originalToken);
    return newFacet;
}

This approach copies the concurrency token from the existing facet to a newly instantiated facet, allowing xConnect to accept the replacement without triggering integrity validation errors.

The solution also includes functionality for cases where developers want to swap in a pre-populated facet while maintaining the concurrency token.