4

I'm trying to write a .aspx script to update an existing contact in the experience profile, the basic logic is:

  1. get the contact by e-mail
  2. get a custom facet from the contact
  3. if the facet is null create a new one and fill some properties with random values
  4. else update the properties with some value

The weird thing is the facet is coming null, so I'm creating a new one, but when I call the submit I'm getting the following error:

Exception: Sitecore.XConnect.Operations.FacetOperationException Message: Operation #0, AlreadyExists, Contact {75e750cb-dc05-0000-0000-065e2a461d1a}, CustomExmFacets Source: Sitecore.Xdb.Common.Web

Has someone faced this before?

Here is the whole script

<%@ Page Language="C#" Debug="true"%>
<%@ Import Namespace="Microsoft.Extensions.DependencyInjection" %>
<%@ Import Namespace="Sitecore.XConnect.Collection.Model" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="Sitecore.XConnect" %>
<%@ Import Namespace="Sitecore.XConnect.Client" %>
<%@ Import Namespace="Sitecore.XConnect.Collection.Model" %>
<%@ Import Namespace="Sitecore.XConnect.Client.Configuration" %>
<% 
    var contactListId = new System.Guid("{70D937C2-D809-4CCE-B5B2-07C68DCAD230}");
    int batchSize = 200; // Size of the batch
    string[] facets =
    {
        CollectionModel.FacetKeys.PersonalInformation,
        CollectionModel.FacetKeys.ListSubscriptions,
        "CustomExmFacet"   
    }; 

    List<string> updatedContacts = new List<string>();
    using (XConnectClient client = SitecoreXConnectClientConfiguration.GetClient())
    {
        string email = "[email protected]";
        Sitecore.XConnect.Contact existingContact 
                = client.Get<Contact>(new IdentifiedContactReference("ListManager", email)
                , new ContactExpandOptions(PersonalInformation.DefaultFacetKey));
        if (existingContact == null) {  
            //Update CustomExmFacets type for some existing custom facet in your instance or use a Sitecore default one          
            var facet = existingContact.GetFacet<CustomExmFacets>("CustomExmFacet");
            if (facet == null)
            {   
                // Facet is new
                var newFacet = new CustomExmFacets
                {
                    VideoUrl = videoUrl.Trim(),
                    ThumbnailUrl = thumbnailUrl.Trim()
                }; 
                client.SetFacet<CustomExmFacets>(existingContact, "CustomExmFacet", newFacet);                
            }
            else
            {
                facet.ThumbnailUrl = "https://random.thumbnail.url.com";
                facet.VideoUrl = "https://random.video.url.com";
                client.SetFacet<CustomExmFacets>(existingContact, "CustomExmFacet", facet);
                                        
                updatedContacts.Add(email);         
            }
            client.Submit();
        }              
    }

    %>
<html>
    <head>
        <title>Updated Contact</title>
    </head>
    <body>
        <h1>Updated Contact</h1>
        <%
        foreach (string email in updatedContacts)
        {                
            if (!string.IsNullOrEmpty(email))
            { %>
                <p><% Response.Write(email); %></p>
            <%
            }
        }%>     
    </body>
</html>

3 Answers 3

4

When you retrieve a contact from xConnect, you should specify which facets should be returned with this contact by passing an array of facet keys into the ContactExpandOptions. The only facets that are always returned if they exist are ConsentInfo and MergeInfo as per Sitecore documentation.

So, in your example, the call to client.Get<Contact> should look like:

Sitecore.XConnect.Contact existingContact 
                = client.Get<Contact>(new IdentifiedContactReference("ListManager", email),
                new ContactExpandOptions(PersonalInformation.DefaultFacetKey, "CustomExmFacet"));

If the requested facets exist, they will be added to the contact's Facets dictionary and can be retrieved using GetFacet<T>() method:

var facet = existingContact.GetFacet<CustomExmFacets>("CustomExmFacet");

If you still get null facet after adding "CustomExmFacet" to the ContactExpandOptions, please also check other potential reasons for this:

  • the facet is not set for this contact (this can be checked in the table Contacts of xDB Shard databases)
  • the combination of facet type and key is incorrect (this can be checked in the class where you defined the custom facet, see more details here)
2
  • 1
    Thank you very much, it worked nicely for me, I completely forgot to add the FacetKey on the contact expando object and I couldn't see the issue. Commented Mar 29, 2022 at 16:41
  • @AndréAndrade great, I'm glad it worked! Commented Mar 29, 2022 at 18:46
1

If your existing contact is null and you are sure that you have created this contact before then you can check with an identifier. there can be a chance that you have created the contact with a different identifier. If it does not exist in your database (for example shard0 or shard1) then you need to create a new contact.To create a new contact you update your code as below:

if (existingContact == null) { 
 Contact contact = new Contact(new ContactIdentifier("Identifier", "Source",  ContactIdentifierType.Known));
 client.AddContact(contact);
 // Facet is new
 var newFacet = new CustomExmFacets
 {
    VideoUrl = videoUrl.Trim(),
    ThumbnailUrl = thumbnailUrl.Trim()
 }; 
 client.SetFacet<CustomExmFacets>(contact, "CustomExmFacet", newFacet);                                                          
 client.Submit();
}

for more details you can refer to the blog post and documents mentioned below:

  1. Set contact facets
  2. Create Custom Facet in Sitecore
  3. Work with Custom Facet in Sitecore
1
  • It's not the contact that was coming null but one of it's facets Commented Feb 23, 2023 at 19:25
-1

I think the issue here is with the way the contact is fetched. Your contact may already exist in DB but not identified using email. Make sure to use email as identifier when creating the contact.

2
  • 1
    That is rather a comment, not an answer having a full solution.
    – Marek Musielak
    Commented Mar 29, 2022 at 6:14
  • This should be a comment and not an answer. Commented May 14, 2023 at 10:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.