List Manager: Creating a Contact List from an external source programmatically

Version

Sitecore 8 Update 2 (150223)

    EXM 3 rev 150223

Task

Create a list manager contact list programmatically from an external data source which can be used as a recipient list for an EXM email message.

Details

First we’ll create a recipient list.

The using statements needed:

using Sitecore.Analytics.Data;
using Sitecore.Analytics.DataAccess;
using Sitecore.Analytics.Model;
using Sitecore.Analytics.Model.Entities;
using Sitecore.Analytics.Tracking;
using Sitecore.Configuration;
using Sitecore.Data;
using Sitecore.ListManagement.ContentSearch;
using Sitecore.ListManagement.ContentSearch.Model;
using ContactData = Sitecore.ListManagement.ContentSearch.Model.ContactData;
Create the list and associate contacts with the list
var listManager = Sitecore.Configuration.Factory.CreateObject("contactListManager", false) as ContactListManager;
var list = new ContactList(ListName);
try {
     //Create list if necessary
     listManager.Create(list);
     var listId = list.Id; //is assigned after creation.
     listManager.AssociateContacts(list, GetContactDatas());
}
...

Get the contacts for the list

protected List<ContactData> GetContactDatas()
{
     List<ContactData> returnList = new List<ContactData>();

     // ... Read the external datasource into Identifier, FirstName,LastName,EmailAddress ...
     // ... Loop through each contact read
           // Add or update the contact
           ContactData contact = CreateContact(Identifier, FirstName,LastName,EmailAddress);
           if (contact != null) returnList.Add(contact);

     return returnList;
}

Create or update the contact to associate with the list

// Add contact if the Identifier is not found, otherwise, update the existing contact
protected ContactData CreateContact(string identifier, string firstName, string lastName, string emailAddress)
{
     if (String.IsNullOrEmpty(identifier)) return null;
     var contactRepo = Factory.CreateObject("contactRepository", true) as ContactRepository;
     LeaseOwner leaseOwner = new LeaseOwner(identifier, LeaseOwnerType.OutOfRequestWorker);

     Contact newContact = null;

     LockAttemptResult<Contact> result = contactRepo.TryLoadContact(identifier, leaseOwner, TimeSpan.FromMinutes(1.0));
     switch (result.Status)
     {
          case LockAttemptStatus.Success:
               // Existing Contact
               newContact = result.Object as Contact;

               // Email Facet
               var emailFacet = newContact.GetFacet&lt;IContactEmailAddresses&gt;(_facetEmails); //_facetEmails = "Emails";
               if (!string.IsNullOrEmpty(emailFacet.Preferred))
               {
                    IEmailAddress address = emailFacet.Entries[emailFacet.Preferred];
                    address.SmtpAddress = emailAddress;
                }
                emailFacet.Preferred = _facetEmailPreferred; //_facetEmailPreferred = "Preferred";
                break;
           case LockAttemptStatus.NotFound:
                // New Contact
                ID guid = Sitecore.Data.ID.NewID;
                newContact = contactRepo.CreateContact(guid);
                newContact.Identifiers.Identifier = identifier;

                // Email Facet
                var emailFacetNew = newContact.GetFacet&lt;IContactEmailAddresses&gt;(_facetEmails); //_facetEmails = "Emails";
                emailFacetNew.Entries.Create(_facetEmailPreferred).SmtpAddress = emailAddress;
                emailFacetNew.Preferred = _facetEmailPreferred;

                break;
            default:
                throw new NotImplementedException("Handling of collection database locking failures is not yet implemented.");
     }

     if (newContact != null)
     {
         // Create and Update same once we have the contact
         var personalInfoNew = newContact.GetFacet&lt;IContactPersonalInfo&gt;("Personal");
         personalInfoNew.FirstName = firstName;
         personalInfoNew.Surname = lastName;
     }
     newContact.ContactSaveMode = ContactSaveMode.AlwaysSave;
     try
     {
         contactRepo.SaveContact(newContact,new ContactSaveOptions(true, leaseOwner));
     }
     catch (Exception ExContactNotSaved)
     {
          //if (ExContactNotSaved Error is exists and not testing for existence)
          string message = ExContactNotSaved.Message.ToString();
     }

     return new ContactData()
     {
          Identifier = identifier
     };
}</pre>
<pre>

Here’s an example of an imported contact in Mongo Db with the Contact List associated as a Tag:

SitecoreContactInMongoDbWithContactListTag

The list in Sitecore List Manager:

ListManagerContactListImportFromODS

Advertisements
Posted in Technology. Tags: , . 9 Comments »

9 Responses to “List Manager: Creating a Contact List from an external source programmatically”

  1. List Manager: Segmented List From Custom Rules Using Custom Facet Fields | Horizontal Integration Says:

    […] We’ll start by creating a custom facet with fields with a custom program to import a recipient list and create or update contacts for the list as described here. […]

  2. Gary Says:

    Hi there.
    Great post – I have iimplemented something similar – one question though, when returning back to sitecore and viewing the LIst Manager, the new list is “locked” and stalling at indexing contacts. If I unlock the list and then rebuild “sitecore_list_index” from the control panel/IndexManager I can then view the contacts on an unlocked list.

    Is there any readon why the list is left in a LOCKED state and why the contacts are NOT being indexed autmatically?

    • Marcia Says:

      I recall having issues with Locked lists. One of the reasons in my case was having more than one Sitecore instance using the same Mongo Db indexes (the standard install from Sitecore with many instances my developer pc will have that unless you change the database names (like adding the Sitecore instance name ahead of the name) in the ConnectionString.config for MongoDb indexes. Once I had instances all with their own Mongo Db indexes, my locking issues cleared up.

      Here’s something Sitecore had me try to find out if more than one process was accessing the index.
      The dump file indicates that some files of the ‘sitecore_list_index’ are used by more than one process which leads to IO Exception and can be related to the issue you reported.
      Please perform the following steps and let me know about the results:
      1. Check that Sitecore has enough rights to create/modify the files in the {dataFolder}/indexes/sitecore_list_index folder.
      2. Ensure that there is no other programs (e.g. antivirus) that may lock the file.
      • Use the Process Explorer tool to find out who locked the file (Ctrl + F -> .lock). 
      • Ensure that only one Sitecore instance points to the physical folder where the ‘sitecore_list_index’ index is stored.

  3. Haris Munawar Says:

    Hi and thanks for this valuable piece of code I was looking for last couple of days. I can understand implement the code but maybe I’m not getting it or you can help me telling, that why I am not able to find a property ‘Identifier’ in the Sitecore.ListManagement.ContactSearch.Model.ContactData object ?
    Maybe some reference is missing? I’m using Sitecore 8.1.

    Lot of thanks and regards,
    Haris

  4. Deepen Joshi Says:

    Nice post, but I am facing one issue for the first time listManager.AssociateContacts(list,xxx) works fine and I can see contact added in my list but when I am sending second request contact is not added and no exception.

    After the above scenario, I have read the contact and added to returnList
    if (listManager.GetContacts(list).Count() > 0)
    {
    returnList.AddRange(listManager.GetContacts(list));
    }
    Then I deleted the old list and created new list with same name my list was showing 2 contacts. but I don’t want this approach.

    Can you please help me to figure it out.

  5. Gosia Says:

    HI
    I have “The type or namespace name could not be found”
    for
    LockAttemptResult
    and
    ContactSaveOptions()

    Can You please help me

  6. Gosia Says:

    I have an issue with locked list too and I have more than one Sitecore instance using the same MongoDB but I do not understand how exactly resolve this issue. Should I rename analytics database in MongoDB? What do I need to change in ConnectionString.config file?

  7. Murali Says:

    hello All, I’m having issue in adding the email to the contacts. The first name and the last name is getting added to the list. but the email is not getting added.

    Also, i need to ope the existing list in the listmanager instead of creating a new list


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: