unveiled a Sitecore connect to Salesforce bug

bug

It is always a great feeling when you did not mess up or cause an issue and it was parceled along with the installation you had done. Can not explain it, but, hey still it was not me. 🙂

So, I bumped in to this issue while doing super thorough tests on new facet fields I just added to my facet and did an effort to push that additional information when available all through the town to Salesforce CRM and to SFMC. While running this tests, I wanted to quickly ensure a Salesforce contact is flagged as “Updated”, so, the next connector run will try and update the record on Sitecore. In effort to flag that I cleared a field that has data in it.

The connector ran as expected, picked up contact as I just edited, but, I did not see field get updated on xConnect. It still had old CRM value and was not updated to Null/Empty. Which is super weird and not expected. At the end of the day, the role of connector is to keep data in sync between platforms. So, empty data should map to empty data and not outdated old data from CRM. This to me is a data integrity issue if it really matters to clients to keep them the contacts truly in sync. So, I loaded a support ticket just to confirm if this is connector current behavior or did I do a grave mistake some where in my setup or configuration or mapping.

Today, Sitecore support confirmed that this indeed is a bug and created a bug on their system. I do not know why, but, I feel like I accomplished some thing by uncovering this pesky data issue. lol Here is the ticket number 441899 and I am all excited to track this probably in couple next releases – KB853187 and KB951718.

Handling different types to map to Salesforce

different things

I recently had a requirement that I was building upon which requires me to store couple additional fields on my xConnect Facet. I had to also show them on Experience profile, push this data when available from Sitecore to Salesforce and back. This additional information should also be available on SFMC when it is available. I knew the drill and did what I had to make this happen. String fields mapping was pretty straight forward and had done it couple times before this drill, so, will not focus on that, you can have a look at my other blog posts which should cover this information.

So, with this requirement we had different types of data that we had to map. For example, we had Boolean, DateTime, Currency and Number to new a few. For every single type of this, we need different handling to ensure the data maps to Salesforce and back successfully. Let’s see how its done:

Step 1: Extend your Facet with all the additional information

        public bool HasDonated { get; set; }
        public DateTime? MostRecentGiveLivelDonationDate { get; set; }
        public DateTime? MostRecentVoicifyDonationDate { get; set; }
        public int EngagementScore { get; set; }
        public decimal GiveLivelyDonationAmount { get; set; }
        public decimal VoicifyDonationAmount { get; set; }

As you can see we have bool, datetime (ensure this is defined nullable, if not, you will be in deep shit and mappings wont work to CRM and SFMC). Now, next up, lets see how mappings should be handled differently and special use of transformers might be needed. Let’s see on each case, how to properly handle. Do note this also depends on data direction, that is, if mapping is from Sitecore to Salesforce or from Salesforce to Sitecore. I will not cover steps needed to ensure this new additional fields are available to be utilized by updating custom collection model json and items. There is a whole different blog post for that.

Boolean Mapping:

This is the easiest one. 🙂 No special handling needed, it should simply work with same process we followed before here

DateTime Mapping:

I would like to stress again how important it is to define this property as nullable. See code snippet above and follow that. Do not waste hours of debugging like I did. 🙂

From Salesforce to Sitecore – See highlighted, it is available OOTB, just ensure you add this to ensure mapping works
From Sitecore to Salesforce – See highlighted, it is available OOTB, just ensure you add this to ensure mapping works

Int mapping:

From Salesforce to Sitecore – See highlighted, this is a new value reader that I had to add to ensure the mapping works and data flows properly.
Definition of value reader that is used as transformer in the step above. It is very important that Target type entered matches .Net type exactly as format shown. If you give just Int or Int32, it will not work.

Note: No special handling is needed to push this type from Sitecore to Salesforce, it just works just fine.

Decimal Mapping:

Very similar to int mapping noted above. I will add few screenshots for reference.

Note: No special handling is needed to push this type from Sitecore to Salesforce, it just works just fine.

Now this might seem pretty straight forward, but, this took me hours to figure out why something is not working as expected. Because there multiple point of failures and I was not able to put a finger on to why. When mappings fail, the logs were not very helpful, so, this required lot of trial and error to actually come up with solution for each of this use case. Hope this helps some one doing some gymnastics with Salesforce and SFMC.

Build Error on TDS Squashed

similar

Remember the feeling when you know you saw a similar error before, but, can not recollect what was done to resolve that? I spent more than half my day battling something very similar that I had seen before, but, no matter what I did from re-collection it did not work. Let me take you through what happened.

Alright, I am trying to set up Azure pipeline to use TDS Web Deploy for very first time. Already first time things, I am usually extra cautious, skeptical and may be not as confident as normal. To top that off, when I struggle to solve something very familiar, it does something to me, I feel like *****. I was burnt out by the end of it, but, good news is that this issue is squashed and I am on to next step.

Okay, here is the story! I was being a good girl and following the steps noted here to get Web Deploy TDS done right via Azure Devops to build and generate artifacts from solution hosted on Azure Devops. I thought I was doing well, until the install of Hedgehog TDS Development Nuget package. So, I opened up Package Manager Console -> selected source as nuget.org and then selected the project to which I need to install the package. It did its thing and seemed alright. For my sanity, I wanted to rebuild the project to which I had done changes and boom, I get a huuuuuge error message which is the error you might have seen at some point of time working with TDS. Full error block below:

The "VerifyTDSVersion" task failed unexpectedly.
System.IO.FileLoadException: API restriction: The assembly 'file:///C:\Users\deepthi.katta\source\repos\project\packages\HedgehogDevelopment.TDS.6.0.0.18\build\HedgehogDevelopment.SitecoreProject.Tasks.dll' has already loaded from a different location. It cannot be loaded from a new location within the same appdomain.
   at System.Reflection.RuntimeAssembly._nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, RuntimeAssembly locationHint, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks)
   at System.Reflection.RuntimeAssembly.nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, RuntimeAssembly locationHint, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks)
   at System.Reflection.RuntimeAssembly.InternalLoadAssemblyName(AssemblyName assemblyRef, Evidence assemblySecurity, RuntimeAssembly reqAssembly, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks)
   at System.Reflection.RuntimeAssembly.InternalLoadFrom(String assemblyFile, Evidence securityEvidence, Byte[] hashValue, AssemblyHashAlgorithm hashAlgorithm, Boolean forIntrospection, Boolean suppressSecurityChecks, StackCrawlMark& stackMark)
   at System.Reflection.Assembly.ReflectionOnlyLoadFrom(String assemblyFile)
   at HedgehogDevelopment.SitecoreProject.Tasks.VerifyTDSVersion.Execute()
   at Microsoft.Build.BackEnd.TaskExecutionHost.Microsoft.Build.BackEnd.ITaskExecutionHost.Execute()
   at Microsoft.Build.BackEnd.TaskBuilder.<ExecuteInstantiatedTask>d__26.MoveNext()	Website.Deploy.TDS	C:\Users\deepthi.katta\source\repos\project\packages\HedgehogDevelopment.TDS.6.0.0.18\build\HedgehogDevelopment.TDS.targets	187	

I can bet my life, I have seen this before. So, I tried re-collecting what I did and also looked up online to find out what I can do to remove this error:

  1. Reloaded the project of concern after unloading it .
  2. Reloaded whole visual studio thinking that would do the magic.
  3. Ensured I matched the Nuget package version to TDS I have on my local. I faintly remembered that could also cause similar error due to conflicting versions.
  4. Removed a new line that got added to project after I installed the package which is below. I know I should not, but, wanted to try it. This worked!!
<Import Project="..\packages\HedgehogDevelopment.TDS.6.0.0.18\build\HedgehogDevelopment.TDS.targets" Condition="Exists('..\packages\HedgehogDevelopment.TDS.6.0.0.18\build\HedgehogDevelopment.TDS.targets')" />

But, I can not remove it though, build on Azure will yell at me and I actually tried it and it literally did yell at me. So, even if the above worked, I can not go with that. I looked at something else on *.csproj file that caught my attention. See below:

<Import Project="$(MSBuildExtensionsPath)\HedgehogDevelopment\SitecoreProject\v9.0\HedgehogDevelopment.SitecoreProject.targets" Condition="Exists('$(MSBuildExtensionsPath)\HedgehogDevelopment\SitecoreProject\v9.0\HedgehogDevelopment.SitecoreProject.targets')" />

I went to the local path and could actually see the HedgehogDevelopment.SitecoreProject.Tasks.dll located in the path noted on import. A quick screenshot below:

This gave me nice clue in right direction. I quickly gathered my patience and did the following in order. Do note that you have to start below on singleton TDS project which does not have internal references to other projects, that should be saved for last. I applied my theory on bundle TDS project and lost hope at first. But, something told me I need to try it again on simple TDS project.

  1. Installed Nuget package via running below command on all TDS projects I have on solution
    Install-Package HedgehogDevelopment.TDS -Version 6.0.0.18
  2. Removed existing import that was loading location above for HedgehogDevelopment.SitecoreProject.targets, I would not need that now that I have all those dll’s loading from Nuget.
  3. Note that #1 and #2 need to be done in specific order. Otherwise, you will get other pesky errors as TDS is thrown off if you remove references before adding one more.
  4. Reload whole Visual studio. Do note that simply reload of project would not help and you will have same error again and again. In my case, I knew I was on right path, but, it did tire me since I tried building as soon as I did above steps.
  5. Rebuild solution and this time you should have successful build if all is well.

After I checked in the above changes, my azure pipeline was a happy camper and was able to generate the artifacts I was after. Yayyyyy!! Moving to next step and I am sure I will face more roadblocks and have to tear them apart. But, this made me real happy on a Friday!!!!

Hope this helps some one save their half day or more!