Saturday, May 9, 2020

Sitecore XC - Not showing selected Catalogs.

 Recently, I found an issue that Sitecore catalogs is not showing any catalogs in the list.

After a quick investigation, I noticed this is because of IIS of commerce authoring was stopped while doing the debugging,

I had restarted the authoring and that resolved the issue.

Friday, May 8, 2020

Sitecore EXM configuration options and steps.

Here is my experience with EXM configuration - I got a requirement to configure the EXM.

I initially did through the SMTP and it worked fine but later on, we came to know to update it to use Sitecore email cloud.

I faced a few issues and here are the details -

Integration options -



I followed this document  - https://kb.sitecore.net/articles/947205 to configure the cloud but found a few issues.

The first

I used the same configuration, 



When I changed the URL to EU - As mentioned below.

 Geo-location     URL  
 EU     https://sparkpost-eu.cloud.sitecore.net  
 US     https://sparkpost.cloud.sitecore.net  

I got below error.


Finally, I came to know that for the cloud it would need an additional license- Ref - https://doc.sitecore.com/users/exm/100/email-experience-manager/en/index-en.html


We had also discussed to Sitecore support team and they also confirmed that it's related to licensing.







Thursday, May 7, 2020

Fix for Sitecore XP and commerce- The password for the account has expired.



Recently, We got this issue on one of the VM where we had Sitecore XP, and Sitecore XC installed.

After a quick investigation, were able to resolve it, here are the details for the quick fix.

The issue was because we had recently updated the password for a local user XX which we used to connect with the local machine with the VM services.

After resetting the password and grating the permission, We were able to resolve this issue.

Easy fix :)

Fix for Sitecore XP and commerce- Sitecore Experience Commerce - Shop CommerceEngineDefaultStorefront does not exist


I recently found this error while browsing the Sitecore commerce catalog item. After a quick investigation, I was able to fix it; below are the quick steps.


Make sure under this commerce settings - you have the same store name which had configured in the site group settings.

/sitecore/Commerce/Commerce Control Panel/Storefront Settings/Storefronts

Under this, the item name (Storefront name) should match with one of the site grouping name here.



Easy fix  :) 

Fix for Sitecore XP and commerce- Could not find and method - AddDataProvider (type: Sitecore.Data.DefaultDatabase)


Recently, I got this issue with the latest commerce local deployment. After a quick investigation, I was able to fix it, here is the step and fix details.

I checked the logs in both Sitecore XP and XC authoring and found below error (XC authoring)

00001 14:07:48 INFO Application startup exception
System.IO.FileLoadException: Could not load file or assembly 'System.IO.Compression, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)
File name: 'System.IO.Compression, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'
   at System.Reflection.RuntimeAssembly.GetExportedTypes(RuntimeAssembly assembly, ObjectHandleOnStack retTypes)
   at System.Reflection.RuntimeAssembly.GetExportedTypes()
   at Sitecore.Framework.Configuration.Strategies.TypeStrategy`1.<>c.<Resolve>b__0_1(Assembly x)
   at System.Linq.Enumerable.<SelectManyIterator>d__17`2.MoveNext()
   at System.Linq.Enumerable.WhereEnumerableIterator`1.MoveNext()
   at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
   at Sitecore.Framework.Configuration.Strategies.Filters.TypeEnvironmentFilter.Filter(IEnumerable`1 input)
   at System.Linq.Enumerable.Aggregate[TSource,TAccumulate](IEnumerable`1 source, TAccumulate seed, Func`3 func)
   at Sitecore.Framework.Configuration.Strategies.StrategyBuilder`1.Using[TNext](IStrategy`2 next)
   at Sitecore.Framework.Runtime.SitecoreBootstrapConfigurationBuilder..ctor(String environmentName)
   at Microsoft.Extensions.DependencyInjection.RuntimeSitecoreServicesConfigurationExtensions.Bootstrap(ISitecoreServicesConfiguration sitecore, IServiceProvider hostServices, String environmentName, Action`1 config)
   at Sitecore.Commerce.Engine.Startup.ConfigureServices(IServiceCollection services)
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at Microsoft.AspNetCore.Hosting.ConventionBasedStartup.ConfigureServices(IServiceCollection services)
   at Microsoft.AspNetCore.Hosting.Internal.WebHost.EnsureApplicationServices()
   at Microsoft.AspNetCore.Hosting.Internal.WebHost.Initialize()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at Microsoft.AspNetCore.Hosting.Internal.WebHost.BuildApplication()


The issue was due to the wrong version of System.IO.Compression ,

I had updated the right version and that resolved the issue.

that's an easy fix :)


Monday, April 27, 2020

SXA Search- tips for troubleshooting and fix

Open the browser and get the SXA query -

The query will look like this -


{
   "endpoint":"//sxa/search/results/",
   "v":"{224530AA-968E-49AB-84B1-AFA3BB52A589}",
   "s":"{3758B0CF-81A6-4DD3-AF1F-9F27A13740D5}",
   "l":"",
   "p":2,
   "defaultSortOrder":"Title,Ascending",
   "sig":"dd",
   "itemid":"{9DF8EC39-57F4-48B4-A2A4-0F13BEF66C63}",
   "autoFireSearch":true
}


this query will be generated based on the scope items and settings like sort order etc.

Now,  check the solr logs -

Path - Your solr root directory/server/logs


Generate the SOLR query and try in Solr admin panel.

Example -

https://localhost:8983/solr/xp930_sxa_master_index/select?q=_template%3A(f6357da575384e9d8caaaa08fd345f5e)

Compare the data, in this example, I fund that the query was searhing for "searchable_b":true, but the actual data was "searchable_b":false,




The problem is that the

"searchable_b":false is false and the query is expecting it "searchable_b":true

Solution - by default all pages under home are searchable and for data items, basically we need to perform two things.

1. Add the _Searchable base template -



2. Go to settings and add the associated content.



Here is the result -

1. Before changes -

2. After changes -


Please let me know if you have any issue in SXA search-related components. I will happy to help :) 

Sitecore SXA Search - Custom SearchQueryToken resolver.

Sitecore SXA provided a few OOTB search query token resolvers as mentioned below.
  1. TaggedTheSameAsCurrentPage|SxaTags
  2. TaggedWithAtLeastOneTagFromCurrentPage|SxaTags
  3. UnderCurrentPage
  4. ExcludeCurrentPage
  5. ItemsOfTheSameTemplateAsTheCurrentPage
  6. ItemsWithTheSameValueInField|FieldName
The resolveSearchQuery tokens basically is a pipeline used to add search filters. This pipeline is defined in the Sitecore.XA.Foundation.Search.config file. 
I've added a new one which is ItemsWithTheSameValueInQueryString|FieldName



Benefit- This custom search resolver can be used anywhere where we want to search/ or filter the SXA result based on the query string (Field and Value).

Example - https://website/searchresult?name1=name1Value&name2=name2Value.

Implementation - Add a new class and implement the ResolveSearchQueryTokensProcessor


 public class ItemsWithTheFieldAndValueInQueryString : ResolveSearchQueryTokensProcessor
    {
        protected string TokenPart { get; } = "ItemsWithTheSameValueInQueryString";

        [SxaTokenKey]
        protected override string TokenKey => FormattableString.Invariant(FormattableStringFactory.
            Create("{0}|FieldName", "ItemsWithTheSameValueInQueryString"));


        public override void Process(ResolveSearchQueryTokensEventArgs args)
        {
            if (args.ContextItem == null)
                return;

            for (var index = 0; index < args.Models.Count; ++index)
            {
                var model = args.Models[index];
                if (!model.Type.Equals("sxa", StringComparison.OrdinalIgnoreCase) || !ContainsToken(model)) continue;
                var inputTokenFields = model.Value.Replace(TokenPart, string.Empty).TrimStart('|');
                var fieldNames = inputTokenFields.Split(',').ToList();
                if (HttpContext.Current.Request.Url != null)
                {
                    var queryCollection = HttpUtility.ParseQueryString
                        (HttpContext.Current.Request.Url.Query);

                    NameValueCollection queryCollectionReferrer = null;
                    if (HttpContext.Current.Request.UrlReferrer != null)
                    {
                        queryCollectionReferrer = HttpUtility.ParseQueryString
                       (HttpContext.Current.Request.UrlReferrer.Query);
                    }
                    

                    foreach (var field in fieldNames)
                    {
                        if (!string.IsNullOrWhiteSpace(field) && !string.IsNullOrWhiteSpace(queryCollection[field]))
                        {
                            args.Models.Insert(index, BuildModel(field.ToLower(), queryCollection.Get(field)));
                        }
                        else if(queryCollectionReferrer != null && !string.IsNullOrWhiteSpace(field) && queryCollectionReferrer.AllKeys.Contains(field) && !string.IsNullOrWhiteSpace(queryCollectionReferrer[field]))
                        {
                            args.Models.Insert(index, BuildModel(field, queryCollectionReferrer.Get(field)));                            
                        }

                    }

                }

                args.Models.Remove(model);
            }
        }
        protected virtual SearchStringModel BuildModel(string replace, string fieldValue)
        {
            return new SearchStringModel("custom", FormattableString.Invariant(FormattableStringFactory.Create("{0}|{1}", replace, fieldValue)))
            {
                Operation = "must"
            };
        }

        protected override bool ContainsToken(SearchStringModel m)
        {
            return Regex.Match(m.Value, FormattableString.Invariant(FormattableStringFactory.Create("{0}\\|[a-zA-Z ]*", "ItemsWithTheSameValueInQueryString"))).Success;
        }
    }

Registration -


 <sitecore role:require="Standalone or ContentDelivery or ContentManagement">
    <pipelines>
      <resolveSearchQueryTokens>
        <processor type="Feature.ItemsWithTheFieldAndValueInQueryString, Namespeace" resolve="true" patch:before = "*[1]" />
      </resolveSearchQueryTokens>
    </pipelines>
  </sitecore>

patch:before = "*[1]"  -  This will be used to keep this patch on the top.


Steps to verify -

Add a SXA Search result component on the page -


You can define the search location, template and this new custom scope item -


Add all the fields required as part of query strings in this custom token resolver.



Add this scope item to the SXA search result component-



Now, you can browse the page and pass the key value in the query string, like this https://website/searchresult?name1=name1Value&name2=name2Value.
 and the SXA result component will provide the updated result :)