Creating a sitecore contact programmatically

Tags:     sitecore-contacts, sitecore-xdb

Recently, I get into a sutuation 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.