I have a Sitecore 8.1-3
instance. I am trying to write some code that lets admin users edit a user's xDB contact information. I have written a general-purpose method in my code that gets a contact object using the user's email address. The idea behind this method is that it could be used within a regular page request (where we are trying to get the current logged in user's contact) or it might be used on an admin page (where we are trying to get the contact that goes with some other user). If the code can't find a contact with the given identifier then it should create a new contact and return it. What I am noticing however is that when my code tries to save the new contact (in the case where it couldn't find a contact using that email address) it throws an error that says "another contact with the same identifier already exists". I can't figure this out. When I use robomongo to look for a contact with that identifier it returns no results.
private Contact GetXdbContact(string identifier)
{
if (Tracker.Current != null && Tracker.Current.Contact != null && Tracker.Current.Contact.Identifiers.Identifier == identifier)
{
//This is the current user
return Tracker.Current.Contact;
}
//There is no Tracker.Current.Contact, so this must be running in some non-user context
var manager = Factory.CreateObject("tracking/contactManager", true) as ContactManager;
var contact = manager.LoadContactReadOnly(identifier);
if (contact == null)
{
//No contact was found so create one
var repository = Factory.CreateObject("tracking/contactRepository", true) as ContactRepository;
var leaseOwner = new LeaseOwner("ADMIN", LeaseOwnerType.OutOfRequestWorker);
var newContact = repository.CreateContact(Guid.NewGuid());
newContact.Identifiers.Identifier = identifier;
newContact.Identifiers.IdentificationLevel = ContactIdentificationLevel.Known;
var options = new ContactSaveOptions(true, leaseOwner);
repository.SaveContact(newContact, options); //EXCEPTION IS THROWN HERE
return newContact;
}
return contact;
}
In our system, the email address is the identifier. So if I call this with [email protected]
as the identifier, the manager does not find any contact, so my code attempts to create a new one. However, when it goes to save the contact it throws the exception below. I can use robomongo to verify that indeed there are not contacts where Identifiers.Identifier == '[email protected]'
, so I'm not really sure what is going on here.
Another contact with the same identifier already exists.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.InvalidOperationException: Another contact with the same identifier already exists.
Source Error:
An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.
Stack Trace:
[InvalidOperationException: Another contact with the same identifier already exists.] Sitecore.Analytics.Data.DataAccess.MongoDb.MongoDbDataAdapterProvider.SaveContactWithIdentifier(IContact contact, ContactSaveOptions saveOptions) +1256 Sitecore.Analytics.Data.DataAccess.MongoDb.c__DisplayClass9.b__7() +25 Sitecore.Analytics.Data.DataAccess.MongoDb.MongoDbDataAdapterProvider.Try(Action action) +173 Sitecore.Analytics.Data.DataAccess.MongoDb.MongoDbDataAdapterProvider.SaveContact(IContact contact, ContactSaveOptions saveOptions) +222 Sitecore.Analytics.Data.ContactRepository.SaveContact(Contact contact, ContactSaveOptions options) +590
Sitecore.Analytics.Tracker.Current.Session.Identify
and pass in the email address so that it creates the contact? Or perhaps my code could hit a custom ASPX page that I create and pass the email address in the URL so that custom ASPX page could start a new session, identify with the email address, the abandon the session. It seems like a hack but maybe it would work.