Showing posts with label Sitecore 9. Show all posts
Showing posts with label Sitecore 9. Show all posts

Thursday, 5 March 2020

Error when using ajax.js (Commerce) and JSON.parse

I found an issue today with the ajax.js file that comes with Sitecore Commerce in Sitecore 9.2.  

I was trying to get a third party js component (Chute) working in Sitecore which loads scripts dynamically, but the component wouldn't display any content.  This particular component displays images in either a carousel or grid.  But after the initial load nothing appeared except for an error in my browser console:

TypeError: data is null  ajax.js:  156:24


This same component worked without any issue, in a non-commerce environment.

After some investigations, it became apparent that the issue was down to the fact that somewhere in the Js files supplied with Commerce the standard JSON.parse function was replaced with a custom function. 

Unfortunately it was missing a null check inside the new function.  I know that as developer we all do this...  However, I wanted to highlight the issue, to save someone some grief when trying to figure out what is going on...

The file in question can be found in the Sitecore content tree here: /sitecore/media library/Base Themes/Commerce Services Theme/Scripts/ajax

Once you download the media content you will get a script called ajax.js.

The offending code @ line 156, can be found just after the JSON.parse equals statement in the block of code shown below:

(function (root, factory) {
    'use strict';
    if (typeof define === 'function' && define.amd) {
      // use AMD define funtion to support AMD modules if in use
      define(['exports'], factory);
    } else if (typeof exports === 'object') {
      // to support CommonJS
      factory(exports);
    }

    // browser global variable
    var AjaxService = {};
    root.AjaxService = AjaxService;
    factory(AjaxService);
  })(this, function (AjaxService) {
    'use strict';

    // Hack >>
    // When debugging is on, Sitecore is returning extra information, we need to strip it from the JSON string
    var jsonParseRef = JSON.parse;

    JSON.parse = function (data) {

      var debugIndex = data.indexOf('<div title="Click here to view the profile."');
      if (debugIndex > 0) {
        data = data.substring(debugIndex, 0, debugIndex);
      }

      return jsonParseRef(data);
    };



You will see in the above function that JSON.parse is updated with a new function, unfortunately the data variable is not checked for null before being used.

Changing the JSON.parse function to: 

JSON.parse = function (data) {

      if(data==null)return null;

      var debugIndex = data.indexOf('<div title="Click here to view the profile."');

      if (debugIndex > 0) {
        data = data.substring(debugIndex, 0, debugIndex);
      }

      return jsonParseRef(data);
    };

Fixes the issue.

Hopefully this might help someone.

Monday, 9 September 2019

Unknown Shape Definition

When running Sitecore 9.1.1 / Solr 7.1.0, we started noticing that the counts of items in an index changed every time we re-indexed the site.

Looking in the logs I saw Solr errors relating to invalid coordinate data:

Exception: SolrNet.Exceptions.SolrConnectionException
Message: <?xml version="1.0" encoding="UTF-8"?>
<response>

<lst name="responseHeader">
  <int name="status">400</int>
  <int name="QTime">545</int>
</lst>
<lst name="error">
  <lst name="metadata">
    <str name="error-class">org.apache.solr.common.SolrException</str>
    <str name="root-error-class">java.text.ParseException</str>
  </lst>
  <str name="msg">ERROR: [doc=sitecore://master/{a885844b-34cd-4eb1-a9d0-2ab1bcc8587a}?lang=en&amp;ver=1&amp;ndx=sitecore_master_index] Error adding field 'coordinate_rpt'='-121.444851,37.712654' msg=Unable to parse shape given formats "lat,lon", "x y" or as WKT because java.text.ParseException: Unknown Shape definition [-121.444851,37.712654]</str>
  <int name="code">400</int>
</lst>
</response>

Source: SolrNet
   at SolrNet.Impl.SolrConnection.PostStream(String relativeUrl, String contentType, Stream content, IEnumerable`1 parameters)
   at SolrNet.Impl.SolrConnection.Post(String relativeUrl, String s)
   at SolrNet.Impl.LowLevelSolrServer.SendAndParseHeader(ISolrCommand cmd)
   at Sitecore.ContentSearch.SolrProvider.SolrBatchUpdateContext.AddRange(IEnumerable`1 group, Int32 groupSize)
   at Sitecore.ContentSearch.SolrProvider.SolrBatchUpdateContext.AddDocument(Object itemToAdd, IExecutionContext[] executionContexts)
   at Sitecore.ContentSearch.SolrProvider.SolrIndexOperations.ApplyPermissionsThenIndex(IProviderUpdateContext context, IIndexable version)
   at Sitecore.ContentSearch.SitecoreItemCrawler.DoAdd(IProviderUpdateContext context, SitecoreIndexableItem indexable)
   at Sitecore.ContentSearch.HierarchicalDataCrawler`1.CrawlItem(T indexable, IProviderUpdateContext context, CrawlState`1 state)

Nested Exception

Exception: System.Net.WebException
Message: The remote server returned an error: (400) Bad Request.
Source: System
   at System.Net.HttpWebRequest.GetResponse()
   at HttpWebAdapters.Adapters.HttpWebRequestAdapter.GetResponse()
   at SolrNet.Impl.SolrConnection.GetResponse(IHttpWebRequest request)
   at SolrNet.Impl.SolrConnection.PostStream(String relativeUrl, String contentType, Stream content, IEnumerable`1 parameters)



It looks like when Solr threw the error, any other items in the same batch were ignored. 

After some investigations, I realized that Sitecore is using a calculated field to index the coordinate data, and so overriding it with additional validation should be be fairly straight forwards.

public class CoordinateValidationComputedIndex : AbstractComputedIndexField
    {
        private static readonly ILog Logger = LogManager.GetLogger("Sitecore.Diagnostics.Crawling") ?? LoggerFactory.GetLogger(typeof(CrawlingLog));
        public override object ComputeFieldValue(IIndexable indexable)
        {
            Item obj = indexable as SitecoreIndexableItem;
            if (obj == null || !obj.Fields.Contains(new ID(Constants.Latitude)) ||
                !obj.Fields.Contains(new ID(Constants.Longitude)))
            {
                return null;
            }

            if (!double.TryParse(obj[new ID(Constants.Latitude)], NumberStyles.Any, CultureInfo.InvariantCulture,
                    out var lat) || !double.TryParse(obj[new ID(Constants.Longitude)], NumberStyles.Any,
                    CultureInfo.InvariantCulture, out var lon))
            {
                return null;
            }

            //Latitude Check -90 - +90
            //Longitude Check -180 - +180
            if (lat < -90 || lat > 90 || lon < -180 || lon > 180)
            {
                Logger.Warn(
                    $"Coordinate validation failed for {obj.ID.Guid:B}:{obj.Paths.FullPath}\n\rWith value of latitude: {lat}, longitude: {lon}\n\r   Latitude should be in range -90 to +90\n\r   Longitude should be in range -180 to +180");
                return null;
            }

            return new Coordinate(lat, lon).ToString();
        }
    }

I then created the following patch file to override the OTB configuration.

<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/" xmlns:role="http://www.sitecore.net/xmlconfig/role/" xmlns:env="http://www.sitecore.net/xmlconfig/env/">
  <sitecore>
    <contentSearch>
      <indexConfigurations>
        <defaultSolrIndexConfiguration type="Sitecore.ContentSearch.SolrProvider.SolrIndexConfiguration, Sitecore.ContentSearch.SolrProvider">
          <documentOptions type="Sitecore.ContentSearch.SolrProvider.SolrDocumentBuilderOptions, Sitecore.ContentSearch.SolrProvider">
            <fields hint="raw:AddComputedIndexField">
              <field patch:instead="*[@fieldName='coordinate']" fieldName="coordinate" returnType="coordinate" >zzz.Feature.Geolocation.ComputedIndex.CoordinateValidationComputedIndex, zzz.Feature</field>
            </fields>
          </documentOptions>
        </defaultSolrIndexConfiguration>
      </indexConfigurations>
    </contentSearch>
  </sitecore>
</configuration>

And this is now what I get in the logs (no Solr errors), and the correct number of items being indexed.

4176 16:17:47 INFO  [Index=sitecore_master_index] Crawler: Processed 5000 items
7988 16:17:47 WARN  Coordinate validation failed for {570326e8-7ae6-4f7a-9354-62670d99c199} : ***Item Path Removed*** with value of latitude:-95.67611, longitude:-95.67611 - 
   Latitude should be in range -90 to +90
   Longitude should be in range -180 to +180
6564 16:17:51 INFO  [Index=sitecore_master_index] Crawler: Processed 6000 items