Use xConnect to update Contact Facets and Identifier in xDB – Sitecore Commerce (XC) 9 Engine

Akshay Sura - Partner

26 Aug 2018

In this video, I am going to walk you through how to use xConnect in a Sitecore Commerce Engine solution.

We will:

  • Add / Update Loyalty Points Facet
  • Add / Update Commerce Customer ID Facet
  • Add an Identifier to an existing Contact
  • Use xConnect in a Sitecore Commerce 9 Engine project

Useful links:

  • Getting Started with xConnect
  • Creating a Contact Facet in xDB Sitecore 9 & xConnect Magic!
  • GitHub Repo: https://github.com/konabos/xConnectLoyalty

If you have any questions or concerns, please get in touch with me. (@akshaysura13 on twitter or on Slack).

  1. using System ;
  2. using System . Collections . Generic ;
  3. using System . Linq ;
  4. using System . Threading . Tasks ;
  5. using Konabos . XConnect . Loyalty . Model . Facets ;
  6. using Konabos . XConnect . Loyalty . Model . Models ;
  7. using Sitecore . Commerce . Core ;
  8. using Sitecore . Commerce . Plugin . Customers ;
  9. using Sitecore . XConnect ;
  10. using Sitecore . XConnect . Client ;
  11. using Sitecore . XConnect . Client . WebApi ;
  12. using Sitecore . XConnect . Collection . Model ;
  13. using Sitecore . XConnect . Schema ;
  14. using Sitecore . Xdb . Common . Web ;
  15. using Plugin . Konabos . Loyalty . Components ;
  16. using Sitecore . Framework . Pipelines ;
  17. using Microsoft . Extensions . Logging ;
  18.  
  19. namespace Konabos . Loyalty . Feature . ReconcilePoints . Pipelines . Blocks
  20. {
  21. public class UpdateCustomerInxDBBlock : PipelineBlock < Customer , Customer , CommercePipelineExecutionContext >
  22. {
  23. private readonly IPersistEntityPipeline _persistEntityPipeline ;
  24. private readonly IFindEntitiesInListPipeline _findEntitiesInListPipeline ;
  25.  
  26. public UpdateCustomerInxDBBlock ( IPersistEntityPipeline persistEntityPipeline , IFindEntitiesInListPipeline findEntitiesInListPipeline )
  27. {
  28. _persistEntityPipeline  = persistEntityPipeline ;
  29. _findEntitiesInListPipeline  = findEntitiesInListPipeline ;
  30. }
  31.  
  32. public override async Task < Customer > Run ( Customer customer , CommercePipelineExecutionContext context )
  33. {
  34. CertificateWebRequestHandlerModifierOptions options  =
  35. CertificateWebRequestHandlerModifierOptions . Parse ( "StoreName=My;StoreLocation=LocalMachine;FindType=FindByThumbprint;FindValue=BC9B7186102910E8F34EE8D9F38138203F7555BA" );
  36.  
  37. var certificateModifier  = new CertificateWebRequestHandlerModifier ( options );
  38.  
  39. List < IHttpClientModifier > clientModifiers  = new List < IHttpClientModifier >();
  40. var timeoutClientModifier  = new TimeoutHttpClientModifier ( new TimeSpan ( 0 , 0 , 20 ));
  41. clientModifiers . Add ( timeoutClientModifier );
  42.  
  43. var collectionClient  = new CollectionWebApiClient ( new Uri ( "https://cateringdemo.xconnect.dev.local/odata" ), clientModifiers , new [] { certificateModifier  });
  44. var searchClient  = new SearchWebApiClient ( new Uri ( "https://cateringdemo.xconnect.dev.local/odata" ), clientModifiers , new [] { certificateModifier  });
  45. var configurationClient  = new ConfigurationWebApiClient ( new Uri ( "https://cateringdemo.xconnect.dev.local/configuration" ), clientModifiers , new [] { certificateModifier  });
  46.  
  47. var cfg  = new XConnectClientConfiguration (
  48. new XdbRuntimeModel ( LoyaltyModel . Model ), collectionClient , searchClient , configurationClient );
  49.  
  50. try
  51. {
  52. await cfg . InitializeAsync ();
  53. }
  54. catch ( XdbModelConflictException ce )
  55. {
  56. context . Logger . LogError ( string . Format ( "{0}-Error in UpdateCustomerInxDBBlock connecting to xDB : {1}" , ( object ) this . Name , ( object ) ce . Message ), Array . Empty < object > ());
  57. }
  58. using ( var client  = new XConnectClient ( cfg ))
  59. {
  60. try
  61. {
  62. IdentifiedContactReference reference  = new IdentifiedContactReference ( "CommerceUser" , string . Concat ( customer . Domain , "\", customer.Email));
  63. Contact existingContact = client.Get<Contact>(reference, new ContactExpandOptions(new string[] { PersonalInformation.DefaultFacetKey, LoyaltyPointsFacet.DefaultFacetKey, LoyaltyCommerceFacet.DefaultFacetKey }));
  64.  
  65. if (existingContact != null)
  66. {
  67. //Add an identifier for the contact with the Commerce Customer Id
  68. string identifierSource = " LoyaltyCustomerId ";
  69. var loyaltyCustomerIdentifier = existingContact.Identifiers.Where(i => i.Source == identifierSource).FirstOrDefault();
  70. if (loyaltyCustomerIdentifier == null)
  71. {
  72. client.AddContactIdentifier(existingContact, new ContactIdentifier(identifierSource, customer.Id.ToString(), ContactIdentifierType.Known));
  73. client.Submit();
  74. }
  75.  
  76. //Add or Update Loyalty Points for the customer
  77. LoyaltyPointsFacet loyaltyPointFacet = existingContact.GetFacet<LoyaltyPointsFacet>(LoyaltyPointsFacet.DefaultFacetKey);
  78. if (loyaltyPointFacet == null)
  79. loyaltyPointFacet = new LoyaltyPointsFacet();
  80.  
  81. loyaltyPointFacet.PointsEarned = customer.GetComponent<LoyaltyComponent>().PointsEarned;
  82. loyaltyPointFacet.PointsSpent = customer.GetComponent<LoyaltyComponent>().PointsSpent;
  83.  
  84. client.SetFacet<LoyaltyPointsFacet>(existingContact, LoyaltyPointsFacet.DefaultFacetKey, loyaltyPointFacet);
  85. client.Submit();
  86.  
  87. //Add or Update the Commerce Customer ID
  88. LoyaltyCommerceFacet loyaltyCommerceFacet = existingContact.GetFacet<LoyaltyCommerceFacet>(LoyaltyCommerceFacet.DefaultFacetKey);
  89. if (loyaltyCommerceFacet == null)
  90. loyaltyCommerceFacet = new LoyaltyCommerceFacet();
  91.  
  92. loyaltyCommerceFacet.CommerceCustomerId = customer.Id.ToString();
  93. client.SetFacet<LoyaltyCommerceFacet>(existingContact, LoyaltyCommerceFacet.DefaultFacetKey, loyaltyCommerceFacet);
  94. client.Submit();
  95. }

  96. }
  97. catch (XdbExecutionException ex)
  98. {
  99. context.Logger.LogError(string.Format(" { 0 }- Error in UpdateCustomerInxDBBlock updating customer  { 2 } to xDB  : { 1 } ", (object)this.Name, (object)ex.Message, customer.Id.ToString()), Array.Empty<object>());
  100. }
  101. }
  102. return customer;
  103. }
  104. }
  105. }

You might get the following error while the running xConnect code:

  1. [ Error ] [ "XdbContextLoggingPlugin" ] XdbContext Batch Execution Exception
  2. System . Net . Http . HttpRequestException : An error occurred  while sending the request . ---> System . Net . WebException : The underlying connection was closed : Could not establish trust relationship  for the SSL / TLS secure channel . ---> System . Security . Authentication . AuthenticationException : The remote certificate  is invalid according to the validation procedure .
  3. at  System . Net . TlsStream . EndWrite ( IAsyncResult asyncResult )
  4. at  System . Net . ConnectStream . WriteHeadersCallback ( IAsyncResult ar )
  5. --- End of inner exception stack trace  ---
  6. at  System . Net . HttpWebRequest . EndGetRequestStream ( IAsyncResult asyncResult , TransportContext & context )
  7. at  System . Net . Http . HttpClientHandler . GetRequestStreamCallback ( IAsyncResult ar )
  8. --- End of inner exception stack trace  ---
  9. at  System . Runtime . ExceptionServices . ExceptionDispatchInfo . Throw ()
  10. at  System . Runtime . CompilerServices . TaskAwaiter . HandleNonSuccessAndDebuggerNotification ( Task task )
  11. at  Sitecore . Xdb . Collection . Search . Solr . SolrReader .< ExecuteQuery > d__14 `1.MoveNext()
  12. --- End of stack trace from previous location where exception was thrown ---
  13. at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
  14. at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
  15. at Sitecore.Xdb.Collection.Search.Solr.SolrReader.<GetSearchResults>d__13` 2.MoveNext ()
  16. --- End of stack trace  from previous location  where exception was thrown  ---
  17. at  System . Runtime . ExceptionServices . ExceptionDispatchInfo . Throw ()
  18. at  System . Runtime . CompilerServices . TaskAwaiter . HandleNonSuccessAndDebuggerNotification ( Task task )
  19. at  Sitecore . Xdb . Collection . Search . Solr . SolrReader .< SearchContacts > d__10 . MoveNext ()
  20. --- End of stack trace  from previous location  where exception was thrown  ---
  21. at  System . Runtime . ExceptionServices . ExceptionDispatchInfo . Throw ()
  22. at  System . Runtime . CompilerServices . TaskAwaiter . HandleNonSuccessAndDebuggerNotification ( Task task )
  23. at  Sitecore . Xdb . Collection . Repository .< SearchContacts > d__11 . MoveNext ()
  24. --- End of stack trace  from previous location  where exception was thrown  ---
  25. at  System . Runtime . ExceptionServices . ExceptionDispatchInfo . Throw ()
  26. at  System . Runtime . CompilerServices . TaskAwaiter . HandleNonSuccessAndDebuggerNotification ( Task task )
  27. at  Sitecore . Xdb . Collection . RepositoryCountersDecorator .< SearchContacts > d__8 . MoveNext ()
  28. --- End of stack trace  from previous location  where exception was thrown  ---
  29. at  System . Runtime . ExceptionServices . ExceptionDispatchInfo . Throw ()
  30. at  System . Runtime . CompilerServices . TaskAwaiter . HandleNonSuccessAndDebuggerNotification ( Task task )
  31. at  Sitecore . XConnect . Service . RepositorySearchInvoker .< Execute > d__7 . MoveNext ()

published

certlm

Please add your Solr cert to the Local Computer\Trusted Root Certification Authorities.

You might get the following error while the running xConnect code:

  1. 2018 - 08 - 25 15 : 01 : 10.453 - 07 : 00 [ Information ] XConnect Test Host Application Start , Machine : "DESKTOP-BCOM790" , Site : "cateringdemo.xconnect.dev.local" , AppId : "/LM/W3SVC/2/ROOT"
  2. 2018 - 08 - 25 15 : 01 : 11.584 - 07 : 00 [ Information ] Certificate Validation Filter Enabled , Thumbprint : BC9B7186102910E8F34EE8D9F38138203F7555BA
  3. 2018 - 08 - 25 15 : 01 : 11.585 - 07 : 00 [ Information ] SSL  Validation Filter Enabled
  4. 2018 - 08 - 25 15 : 01 : 12.865 - 07 : 00 [ Information ] SystemPerformanceCounters Constructor , Instance : cateringdemo . xconnect . dev . local , Path : C : inetpubwwwrootcateringdemo . xconnect . dev . localApp_DataDiagnostics , CounterFilePattern : *. json
  5. 2018 - 08 - 25 15 : 01 : 12.882 - 07 : 00 [ Error ] Access to the registry key  'Global' is denied .
  6. System . UnauthorizedAccessException : Access to the registry key  'Global' is denied .
  7. at  Microsoft . Win32 . RegistryKey . Win32Error ( Int32 errorCode , String str )
  8. at  Microsoft . Win32 . RegistryKey . InternalGetValue ( String name , Object defaultValue , Boolean doNotExpand , Boolean checkSecurity )
  9. at  Microsoft . Win32 . RegistryKey . GetValue ( String name )
  10. at  System . Diagnostics . PerformanceMonitor . GetData ( String item )
  11. at  System . Diagnostics . PerformanceCounterLib . GetPerformanceData ( String item )
  12. at  System . Diagnostics . PerformanceCounterLib . get_CategoryTable ()
  13. at  System . Diagnostics . PerformanceCounterLib . CategoryExists ( String machine , String category )
  14. at  System . Diagnostics . PerformanceCounterCategory . Exists ( String categoryName , String machineName )
  15. at  System . Linq . Enumerable . WhereEnumerableIterator `1.MoveNext()
  16. at System.Linq.Buffer` 1. . ctor ( IEnumerable `1 source)
  17. at System.Linq.Enumerable.ToArray[TSource](IEnumerable` 1 source )
  18. at  Sitecore . XConnect . Diagnostics . PerformanceCounters . SystemPerformanceCounters . Initialize ( String counterFilePattern )
  19. 2018 - 08 - 25 15 : 01 : 13.331 - 07 : 00 [ Information ] Create "XdbContextLoggingPlugin"
  20. 2018 - 08 - 25 15 : 01 : 13.341 - 07 : 00 [ Information ] Register "XdbContextLoggingPlugin"

Please add your xConnect site app pool user to the Performance Monitor Users group.

Follow us on Twitter Follow us on LinkedIn Follow us on YouTube


Sign up to our newsletter

Share on social media

Akshay Sura

Akshay is a nine-time Sitecore MVP and a two-time Kontent.ai. In addition to his work as a solution architect, Akshay is also one of the founders of SUGCON North America 2015, SUGCON India 2018 & 2019, Unofficial Sitecore Training, and Sitecore Slack.

Akshay founded and continues to run the Sitecore Hackathon. As one of the founding partners of Konabos Consulting, Akshay will continue to work with clients to lead projects and mentor their existing teams.


Subscribe to newsletter