1

In Sitecore 9.x the contact identifiers are case sensitive and users are uploading contact lists with emails that are not cased correctly. Before I start digging through the pipelines, anyone know off the top of their head the pipeline where the contact import data is being processed. So I can add a pipeline that will case them properly.

There is the pipeline listManagement.importMediaContacts and that leads to Sitecore.ListManagement.Services.Pipelines.ImportMediaContacts.GetContactsFromStream

That leads to

<streamContactImporter type="Sitecore.ListManagement.Import.StreamContactImporter, Sitecore.ListManagement">
   <param ref="/sitecore/import/contactSource"/>
   <param ref="/sitecore/import/contactImporter"/>
   <param type="Sitecore.Abstractions.BaseLog, Sitecore.Kernel" resolve="true"/>
</streamContactImporter>

The source is this. I think maybe I can override in here.

<contactSource type="Sitecore.ListManagement.Import.ValidIdentifierSourceFilter, Sitecore.ListManagement">
    <param type="Sitecore.ListManagement.Import.UniqueIdentifierFilter, Sitecore.ListManagement">
        <param type="Sitecore.ListManagement.Import.RequiredFieldsFilter, Sitecore.ListManagement">
            <param type="Sitecore.ListManagement.Import.IdentifierIndexRangeFilter, Sitecore.ListManagement">
                <param type="Sitecore.ListManagement.Import.CsvContactSource, Sitecore.ListManagement">
                    <param type="Sitecore.ListManagement.Import.CsvReader, Sitecore.ListManagement" resolve="true"/>
                </param>
            </param>
        </param>
    </param>
    <param type="Sitecore.Abstractions.BaseLog, Sitecore.Kernel" resolve="true"/>
</contactSource>

Or I can write my own xConnect importer

<contactImporter type="Sitecore.ListManagement.Import.RequiredMappingFieldRangeValidator, Sitecore.ListManagement">
    <param type="Sitecore.ListManagement.Import.ObservableContactImporter, Sitecore.ListManagement">
        <param type="Sitecore.ListManagement.Import.BatchContactImporter, Sitecore.ListManagement">
            <param type="Sitecore.ListManagement.XConnect.Web.Import.XConnectContactImporter, Sitecore.ListManagement.XConnect.Web">
                <param type="Sitecore.ListManagement.XConnect.Web.XdbClientFactory, Sitecore.ListManagement.XConnect.Web"/>
                    <param ref="/sitecore/import/facetMapper"/>
                        <param type="Sitecore.ListManagement.Configuration.ListManagementSettings, Sitecore.ListManagement" resolve="true"/>
                        <param type="Sitecore.Abstractions.BaseLog, Sitecore.Kernel" resolve="true"/>
                    </param>
                <param type="Sitecore.ListManagement.Configuration.ListManagementSettings, Sitecore.ListManagement" resolve="true"/>
            </param>
        <param type="Sitecore.ListManagement.Operations.IListOperationRepository, Sitecore.ListManagement" resolve="true"/>
    </param>
</contactImporter>
0

I found that if I override the import task Sitecore.ListManagement.XConnect.Web.Import.XConnectContactImporter I had access to the IdentifiedContactReference and could control the case of the identifiers.

The code

namespace Sitecore.Foundation.Links.Import
{
    using Sitecore.Abstractions;
    using Sitecore.Diagnostics;
    using Sitecore.ListManagement.Configuration;
    using Sitecore.ListManagement.Import;
    using Sitecore.XConnect;
    using Sitecore.XConnect.Client;
    using Sitecore.XConnect.Operations;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.Linq;
    using System.Threading.Tasks;
    using Sitecore.ListManagement.XConnect.Web;
    using Sitecore.ListManagement.XConnect.Web.Import;

    public class XConnectContactImporter : IContactImporter
    {
        private readonly IFacetMapper _facetMapper;
        private readonly XdbRequestPerformer _xdbRequestPerformer;

        public XConnectContactImporter(
          IXdbClientFactory xdbClientFactory,
          IFacetMapper facetMapper,
          ListManagementSettings settings,
          BaseLog log)
        {
            Assert.ArgumentNotNull(xdbClientFactory, nameof(xdbClientFactory));
            Assert.ArgumentNotNull(facetMapper, nameof(facetMapper));
            Assert.ArgumentNotNull(settings, nameof(settings));
            Assert.ArgumentNotNull(log, nameof(log));
            this._facetMapper = facetMapper;
            this._xdbRequestPerformer = new XdbRequestPerformer(xdbClientFactory, settings, log);
        }

        public async Task Import(
          IEnumerable<string[]> contacts,
          ImportOptions options,
          ImportSummary summary)
        {
            Assert.ArgumentNotNull(contacts, nameof(contacts));
            Assert.ArgumentNotNull(options, nameof(options));
            var mappings = options.Mappings;
            var identifierIndex = mappings.IdentifierIndex;
            var facetKeys = mappings.Facets.ToArray();
            await Task.Run(() => this._xdbRequestPerformer.RequestWithRetry(client =>
            {
                var dictionary = new Dictionary<IdentifiedContactReference, string[]>();
                foreach (var contact in contacts)
                {
                    if (mappings.GetIdentifierSourceValue(contact) == Sitecore.Foundation.XdbModels.Identifiers.EmailAddress)
                    {
                        dictionary.Add(new IdentifiedContactReference(Sitecore.Foundation.XdbModels.Identifiers.EmailAddress, contact[identifierIndex].ToLower()), contact);
                    }
                    else if (mappings.GetIdentifierSourceValue(contact) == Sitecore.Foundation.XdbModels.Identifiers.SwimmerIdLoginIdentifier)
                    {
                        dictionary.Add(new IdentifiedContactReference(Sitecore.Foundation.XdbModels.Identifiers.IdLoginIdentifier, contact[identifierIndex].ToUpper()), contact);
                    }
                    else
                        dictionary.Add(new IdentifiedContactReference(mappings.GetIdentifierSourceValue(contact), contact[identifierIndex]), contact);
                }

                foreach (var entityLookupResult in client.Get(dictionary.Keys, new ContactExpandOptions(facetKeys)) 
                                                   ?? (IReadOnlyCollection<IEntityLookupResult<Contact>>)new ReadOnlyCollection<IEntityLookupResult<Contact>>(new List<IEntityLookupResult<Contact>>()))
                {
                    var reference = (IdentifiedContactReference)entityLookupResult.Reference;
                    Contact contact;
                    if (entityLookupResult.Exists)
                        contact = entityLookupResult.Entity;
                    else
                        contact = new Contact(new ContactIdentifier(reference.Source, reference.Identifier, ContactIdentifierType.Known));
                    var compositeMappingResult = new CompositeMappingResult(entityLookupResult.Exists);
                    foreach (var str in facetKeys)
                        compositeMappingResult.Add(this._facetMapper.Map(str, contact.GetFacet<Facet>(str), mappings, dictionary[reference]));
                    compositeMappingResult.Accept(client, contact, summary);
                }
                client.Submit();
                if (client.SyncToken == null)
                    return;
                summary.SyncToken = client.SyncToken;
            }, "importing"));
        }
    }
}

The patch

Here is the config

<?xml version="1.0" encoding="utf-8"?>
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/" xmlns:set="http://www.sitecore.net/xmlconfig/set/">
    <sitecore>
        <import>
            <contactImporter type="Sitecore.ListManagement.Import.RequiredMappingFieldRangeValidator, Sitecore.ListManagement">
                <param type="Sitecore.ListManagement.Import.ObservableContactImporter, Sitecore.ListManagement">
                    <param type="Sitecore.ListManagement.Import.BatchContactImporter, Sitecore.ListManagement">

                        <param type="Sitecore.ListManagement.XConnect.Web.Import.XConnectContactImporter, Sitecore.ListManagement.XConnect.Web" >
                            <patch:attribute name="type">Sitecore.Foundation.Lists.Import.XConnectContactImporter, Sitecore.Foundation.Lists</patch:attribute>
                        </param>

                    </param>
                    <param type="Sitecore.ListManagement.Operations.IListOperationRepository, Sitecore.ListManagement" resolve ="true"/>
                </param>
            </contactImporter>
        </import>
    </sitecore>
</configuration>

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.