Friday, August 29, 2014

Multiple CustomerContacts created in EPiServer Commerce

Creating a CustomerContact from a MembershipUser is something you'll run into quite quick when developing a Commerce site. Now, what's wrong with this piece of code?

public CustomerContact CreateUser(MembershipUser user, string firstname, string lastname)
{
   CustomerContact customerContact = CustomerContact.CreateInstance(user);

   SecurityContext.Current.AssignUserToGlobalRole(user, AppRoles.EveryoneRole);
   SecurityContext.Current.AssignUserToGlobalRole(user, AppRoles.RegisteredRole);

   customerContact.FullName = string.Join(" ", firstname, lastname);
   customerContact.FirstName = firstname;
   customerContact.LastName = lastname;
   customerContact.Email = user.Email;
   return customerContact;
}

To me, this piece of code looked fine until I ran it. What happened was that I received two CustomerContacts, one containing the correct information such as firstname, lastname and fullname. The other CustomerContact only contained the email address, nothing else. Both of them were linked to the correct account.

So what happened? Well, according to the EPiServer Commerce SDK we need to save the CustomerContact before calling AssignUserToGlobalRole"The CustomerContact associated with the user must be saved before calling this method. Otherwise contact information might be lost." 

In this case, contact information was not lost, it was duplicated. So what's the correct way of doing it then? We have to call SaveChanges on the CustomerContact before assigning the roles:

public CustomerContact CreateUser(MembershipUser user, string firstname, string lastname)
{
   CustomerContact customerContact = CustomerContact.CreateInstance(user);
   customerContact.SaveChanges();
   
   SecurityContext.Current.AssignUserToGlobalRole(user, AppRoles.EveryoneRole);
   SecurityContext.Current.AssignUserToGlobalRole(user, AppRoles.RegisteredRole);

   customerContact.FullName = string.Join(" ", firstname, lastname);
   customerContact.FirstName = firstname;
   customerContact.LastName = lastname;
   customerContact.Email = user.Email;
   return customerContact;
}

2 comments:

  1. Wouldn't you need to call SaveChanges() again before returning customerContact? In order to persist all the data.

    ReplyDelete
    Replies
    1. Yes, you should. In my case, I add a couple of adresses to the returned customerContact before I call SaveChanges(), that's why it's not included in the CreateUser method.

      Delete