Recently, I get into a situation where i need to create a Sitecore contact when a user submits a contact form. I find it hard while finding a right solution for this. So i am sharing my solution here.
Here is the SitecoreContactManager.cs which deals with creating and updating contacts in xdb:
public class SitecoreContactManager
{
private ContactManager _manager = Sitecore.Configuration.Factory.CreateObject("tracking/contactManager", true) as ContactManager;
private ContactRepository _repository = Sitecore.Configuration.Factory.CreateObject("tracking/contactRepository", true) as ContactRepository;
public ContactManager XdbContactManager
{
get { return _manager; }
}
public ContactRepository XdbContactRepository
{
get { return _repository; }
}
public Contact GetXdbContact(string identifier)
{
var contact = XdbContactRepository.LoadContactReadOnly(identifier);
if (contact != null) return contact;
var leaseOwner = new LeaseOwner(GetType() + Guid.NewGuid().ToString(), LeaseOwnerType.OutOfRequestWorker);
contact = XdbContactRepository.CreateContact(Guid.NewGuid());
if (contact == null) return null;
contact.Identifiers.Identifier = identifier;
//Setting these values allows processing and aggregation to process this contact without erroring.
contact.System.Value = 0;
contact.System.VisitCount = 0;
//MAKE OTHER Contact Changes here too if you need to on Create.
XdbContactRepository.SaveContact(contact, new ContactSaveOptions(true, leaseOwner));
return contact;
}
public bool UpdateXdbContact(string identifier, string firstName, string lastName, string telephone)
{
try
{
var currentContact = GetXdbContact(identifier);
if (currentContact == null)
return false;
var lockResult = XdbContactManager.TryLoadContact(currentContact.ContactId);
Contact updatedContact = currentContact;
switch (lockResult.Status)
{
case LockAttemptStatus.Success:
var lockedContact = lockResult.Object;
lockedContact.ContactSaveMode = ContactSaveMode.AlwaysSave;
updatedContact = UpdateContactInfo(lockedContact, firstName, lastName, telephone, identifier); //this method should do work on lockedContact and return lockedContact. this then saves it as updatedContact.
break;
case LockAttemptStatus.NotFound:
updatedContact = currentContact;
break;
default:
var exception = new Exception(GetType() + " Contact could not be locked - " + currentContact.ContactId);
Sitecore.Diagnostics.Log.Error(string.Format("[{1}:SaveContactInfoToXdb] Can't Lock or Find xDB Contact {0}", currentContact.ContactId, GetType()), exception);
break;
}
//Save Contact Information - This is the ContactManager method to use
XdbContactManager.SaveAndReleaseContact(updatedContact);
return true;
}
catch (Exception exception)
{
Sitecore.Diagnostics.Log.Error($"Error in updating contact identifier {identifier}", exception);
}
return false;
}
private Contact UpdateContactInfo(Contact lockedContact, string firstName, string lastName, string telephone, string email)
{
try
{
var personalInfo = lockedContact.GetFacet<IContactPersonalInfo>("Personal");
personalInfo.FirstName = firstName;
personalInfo.Surname = lastName;
var contactEmails = lockedContact.GetFacet<IContactEmailAddresses>("Emails");
if (contactEmails != null)
{
IEmailAddress contactEmail = null;
if (contactEmails.Entries.Contains("Work E-Mail"))
{
contactEmail = contactEmails.Entries["Work E-Mail"];
}
else
{
contactEmail = contactEmails.Entries.Create("Work E-Mail");
contactEmails.Preferred = "Work E-Mail";
}
contactEmail.SmtpAddress = email;
}
var cotactphoneNumbers = lockedContact.GetFacet<IContactPhoneNumbers>("Phone Numbers");
if (cotactphoneNumbers != null)
{
IPhoneNumber work = null;
if (cotactphoneNumbers.Entries.Contains("Work"))
{
work = cotactphoneNumbers.Entries["Work"];
}
else
{
work = cotactphoneNumbers.Entries.Create("Work");
cotactphoneNumbers.Preferred = "Work";
}
work.Number = telephone;
}
}
catch (Exception exception)
{
Sitecore.Diagnostics.Log.Error($"Error in updating contact identifier {lockedContact.Identifiers.Identifier}", exception);
return null;
}
return lockedContact;
}
}
Code i used on contact form submit:
private void CreateUpdateContactInXdb(FormDetailsModel model)
{
try
{
//Identify the user
Tracker.Current.Session.Identify(model.Email);
//get the contact
var contact = Tracker.Current.Session.Contact;
if (contact != null)
{
//Update contact
SitecoreContactManager.UpdateXdbContact(model.Email, model.FirstName, model.LastName, model.Phone);
Tracker.Current.Interaction.Value += 100;
}
else
{
//Create contact
Tracker.Current.Interaction.Value = 100;
Tracker.Current.Session.Contact = SitecoreContactManager.GetXdbContact(model.Email);
}
}
catch (Exception exception)
{
Sitecore.Diagnostics.Log.Error($"error in creating or updating contact for identifier {model.Email}", exception);
}
}
Please look at this blogpost which helped me in finding the right solution for more details on this.