I am using Sitecore 9.0.1 and I am trying to insert custom tokens to email in EXM. I followed Sitecore's documentation and spent hours investigating possible solutions but somehow my tokens did not get filled.
Here are the steps that I took:
- Created Facet,
- Created Model for facet and then deployed model (JSON to xConnect, this should work for xconnect side),
- Added new fields to /sitecore/client/Applications/List Manager/Dialogs/ImportWizardDialog/PageSettings/TabControl Parameters/Map/ImportModel named them FacetName_FieldName,
- Created FacetMapper and PropertyTokenMap and configured them.
I checked multiple times for possible configuration error, but I can't get tokens to fill.
Can someone help me debug this?
Here is the code reference :
Facet:
namespace Sitecore.Feature.EmailConfiguration.Facets{
[Serializable]
[FacetKey(DefaultFacetKey)]
public class EmailUser:Sitecore.XConnect.Facet
{
public const string DefaultFacetKey = "EmailUser";
public string Username { get; set; }
public string Password { get; set; }
public EmailUser()
{
}
}
}
Model:
namespace Sitecore.Feature.EmailConfiguration.Models
{
public class EmailUserModel
{
public static XdbModel Model { get; } = EmailUserModel.BuildModel();
public static XdbModel BuildModel()
{
XdbModelBuilder modelBuilder = new XdbModelBuilder("EmailUserModel", new XdbModelVersion(0, 1));
modelBuilder.ReferenceModel(Sitecore.XConnect.Collection.Model.CollectionModel.Model);
modelBuilder.DefineFacet<Contact, EmailUser>(EmailUser.DefaultFacetKey);
return modelBuilder.BuildModel();
}
}
}
FacetMapper:
namespace Sitecore.Feature.EmailConfiguration.Mappers
{
public class EmailUserFacetMapper : IFacetMapper
{
private readonly PreferredEmailFacetMapper mapper;
public EmailUserFacetMapper(): this(CollectionModel.FacetKeys.AddressList)
{
}
public EmailUserFacetMapper(string facetName)
{
Assert.ArgumentNotNull(facetName, nameof(facetName));
this.FacetName = facetName;
}
public string FacetName { get; }
public MappingResult Map(string facetKey, Facet facet, ContactMappingInfo mappings, string[] data)
{
using (EventLog eventLog = new EventLog("Application"))
{
eventLog.Source = "Application";
eventLog.WriteEntry("EmailUserFacetMapperCalled facetKey:" +facetKey+" data"+ string.Join("; ", data));
}
if (facetKey != this.FacetName)
{
return new NoMatch(facetKey);
}
var emailUser = new EmailUser();
var username = mappings.GetValue("EmailUser_Username", data);
var password = mappings.GetValue("EmailUser_Password",data);
if (!string.IsNullOrEmpty(username)) { emailUser.Username = username; }
if (!string.IsNullOrEmpty(password)) { emailUser.Password = password; }
return (MappingResult)new FacetMapped(facetKey, (Facet) emailUser);
}
}
}
PropertyTokenMap:
namespace Sitecore.Feature.EmailConfiguration.TokenMaps
{
public class EmailUserPropertyTokenMap : DefaultRecipientPropertyTokenMap
{
protected static readonly MethodInfo GetUsernameValue = typeof(FacetExtensions).GetMethod(nameof(FacetExtensions.GetUsernameValue), new[] { typeof(EmailUser) });
protected static readonly MethodInfo GetPasswordValue = typeof(FacetExtensions).GetMethod(nameof(FacetExtensions.GetPasswordValue), new[] { typeof(EmailUser) });
static EmailUserPropertyTokenMap()
{
if (TokenBindings == null)
{
TokenBindings = new Dictionary<Token, RecipientPropertyTokenBinding>();
}
RecipientPropertyTokenBinding usernameTokenBinding = RecipientPropertyTokenBinding.Build<EmailUser>(new Token("username"), null, GetUsernameValue);
RecipientPropertyTokenBinding passwordTokenBinding = RecipientPropertyTokenBinding.Build<EmailUser>(new Token("password"), null, GetPasswordValue);
TokenBindings.Add(usernameTokenBinding.Token, usernameTokenBinding);
TokenBindings.Add(passwordTokenBinding.Token, passwordTokenBinding);
}
}
public static class FacetExtensions
{
public static string GetUsernameValue(this EmailUser facet)
{
return facet.Username;
}
public static string GetPasswordValue(this EmailUser facet)
{
return facet.Password;
}
}
}
Xml config:
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/" xmlns:set="http://www.sitecore.net/xmlconfig/set">
<sitecore>
<exm>
<dispatchTask type="Sitecore.Feature.EmailConfiguration.DispatchTasks.EmailUserDispatchTask, Sitecore.Feature.EmailConfiguration" patch:instead="*[@type='Sitecore.EmailCampaign.Cm.Dispatch.DispatchTask, Sitecore.EmailCampaign.Cm']">
<param ref="exm/dispatchFailedTaskPool"/>
<param desc="recipientValidator" ref="exm/recipientValidator" />
<param desc="contactService" ref="exm/contactService" />
<param desc="dataProvider" ref="exm/dataProvider" />
<param desc="itemUtil" ref="exm/itemUtil" />
<param desc="eventDataService" ref="exm/eventDataService" />
<param desc="dispatchManager" ref="exm/dispatchManager" />
<param desc="emailAddressHistoryManager" ref="exm/emailAddressHistoryManager" />
<param desc="recipientManagerFactory" ref="exm/recipientManagerFactory" />
<param desc="sentHistoryManager" ref="exm/sentHistoryManager" />
</dispatchTask>
</exm>
<recipients>
<recipientPropertyTokenMap type="Sitecore.Feature.EmailConfiguration.TokenMaps.EmailUserPropertyTokenMap, Sitecore.Feature.EmailConfiguration" singleInstance="true" patch:instead="*[@type='Sitecore.Modules.EmailCampaign.Core.Personalization.DefaultRecipientPropertyTokenMap, Sitecore.EmailCampaign']" />
</recipients>
<import>
<facetMappers hint="list:Add">
<facetMapper type="Sitecore.Feature.EmailConfiguration.Mappers.EmailUserFacetMapper,Sitecore.Feature.EmailConfiguration" />
</facetMappers>
</import>
<settings>
<setting name="ListManagement.Import.FacetsToMap">
<set:attribute name="value">Emails|Personal|Addresses|EmailUser</set:attribute>
</setting>
</settings>
<xconnect>
<runtime type="Sitecore.XConnect.Client.Configuration.RuntimeModelConfiguration,Sitecore.XConnect.Client.Configuration">
<schemas hint="list:AddModelConfiguration">
<schema name="EmailUserModel" type="Sitecore.XConnect.Client.Configuration.StaticModelConfiguration,Sitecore.XConnect.Client.Configuration">
<param desc="modeltype">Sitecore.Feature.EmailConfiguration.Models.EmailUserModel,Sitecore.Feature.EmailConfiguration</param>
</schema>
</schemas>
</runtime>
</xconnect>
</sitecore>
</configuration>
Update: I forgot to put Dispatch task, also i tried debuging this and it loads only 4 other facets without my facet. My test case is load csv i list Manager and then i send test tokens including default and my tokens. Default tokens work but my tokens are empty.
DispatchTask:
namespace Sitecore.Feature.EmailConfiguration.DispatchTasks
{
public class EmailUserDispatchTask :DispatchTask
{
private IContactService _contactService;
public EmailUserDispatchTask(ShortRunningTaskPool taskPool, IRecipientValidator recipientValidator, IContactService contactService, EcmDataProvider dataProvider, ItemUtilExt itemUtil, IEventDataService eventDataService, IDispatchManager dispatchManager, EmailAddressHistoryManager emailAddressHistoryManager, IRecipientManagerFactory recipientManagerFactory, SentMessageManager sentMessageManager)
: base(taskPool, recipientValidator, contactService, dataProvider, itemUtil, eventDataService, dispatchManager, emailAddressHistoryManager, recipientManagerFactory, sentMessageManager)
{
_contactService = contactService;
}
protected override IReadOnlyCollection<IEntityLookupResult<Contact>> GetContacts(List<DispatchQueueItem> dispatchQueueItems)
{
var test= _contactService.GetContacts(dispatchQueueItems.Select(x => x.ContactIdentifier), PersonalInformation.DefaultFacetKey, EmailAddressList.DefaultFacetKey, ConsentInformation.DefaultFacetKey, PhoneNumberList.DefaultFacetKey, ListSubscriptions.DefaultFacetKey, EmailAddressHistory.DefaultFacetKey, EmailUser.DefaultFacetKey);
return test;
}
}
}
Here is my Json generated for adding model to xconnect to locations xconnect_root/App_data/Models and xconnect_root\App_data\jobs\continuous\IndexWorker\App_data\Models
{
"Name": "EmailUserModel",
"Version": "0.1",
"References": [
{
"Name": "XConnect",
"Version": "1.0"
},
{
"Name": "Sitecore.XConnect.Collection.Model",
"Version": "9.0"
}
],
"Types": {
"Sitecore.Feature.EmailConfiguration.Facets.EmailUser": {
"Type": "Facet",
"BaseType": "Sitecore.XConnect.Facet",
"ClrType": "Sitecore.Feature.EmailConfiguration.Facets.EmailUser, Sitecore.Feature.EmailConfiguration, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null",
"Properties": {
"Username": {
"Type": "String"
},
"Password": {
"Type": "String"
}
}
}
},
"Facets": [
{
"Target": "Contact",
"Name": "EmailUser",
"Type": "Sitecore.Feature.EmailConfiguration.Facets.EmailUser"
}
]
}
Update 2: Seems that my Model does not get registered for some reason. I found information that if facet is registered than it will appear in database {siteprefix}_Xdb.Collection.Shard0].[xdb_collection].[ContactFacets] . Is there working example somewhere of adding model to xconnect?