Devops

Experience Editor error – After parsing a value an unexpected character was encountered: {. Path ‘scLayout’

Abstract Purple Dots@1x

I’ve recently been sparring with a very annoying Sitecore error. It occurs only in Experience Editor, after the Rendering Parameter properties dialog of a rendering is opened, and the user then tries to save the page.

 

sitecore error

This particular Experience Editor error is very frustrating because:
1. It blocks Content Admins from doing their work, and…
2. The fix involves manually tweaking JavaScript files on every affected Sitecore instance.

 

Fix – Take 1

I’ve been working with Sitecore 8.1 instances for the past year (from initial release to most recent update), and have been fixing the issue all over the place by following the advice from this Stack Overflow post: http://stackoverflow.com/questions/35029713/save-return-error-in-sitecore-page-editor/35443212#35443212.

That post identified the JavaScript file and function that was the source of the issue and recommended corrections, which worked perfectly. Easy peasy.

Now Sitecore 8.2 is out, and our function has received a facelift (functionlift?). The error still occurs, and the fix from above no longer helps.

Covid 19
COVID-19: Digital Insights For Enterprise Action

Access Perficient’s latest insights into how you can leverage digital technologies to not only respond to the pandemic, but drive your operations forward and deliver experiences your customers need.

Get Informed

 

Fix – Take 2

I found a newer Stack Exchange post — http://sitecore.stackexchange.com/a/2647 — which gave us a solution for 8.2 from Sitecore Support.

Unfortunately, it did not resolve the error for me. Could be because that post was for 8.2 Initial Release and I’m on 8.2 Update 1. But the JavaScript function where the error is happening is encoding presentation details XML, and the structure of presentation details XML has not changed, so it should be possible to support all 8+ versions with the same code.

I decided to dig in myself. Here are my findings:

Sitecore Support Code

Instructions are to go to Website/sitecore/shell/client/Sitecore/ExperienceEditor/ExperienceEditor.js and to replace the code for postServerRequest function with this updated version.

postServerRequest: function (requestType, commandContext, handler, async) {
var token = $('input[name="__RequestVerificationToken"]').val();

var ajaxData = unescape(JSON.stringify(commandContext));
if (commandContext && commandContext.scLayout){
var obj = JSON.parse(commandContext.scLayout);
if (obj && obj.r && obj.r.d && obj.r.d.forEach){
obj.r.d.forEach(function(x,y){
if (x.r && x.r.forEach) {
x.r.forEach(function(a,z){
var val = a["@par"];
if (val && val.length > 0){
ajaxData = ajaxData.replace(unescape(val), val);
}
});
}
});
}
}

jQuery.ajax({
url: "/-/speak/request/v1/expeditor/" + requestType,
data: {
__RequestVerificationToken: token,
data: ajaxData
},
success: handler,
type: "POST",
async: async != undefined ? async : false
});
}

 

Identity Crisis

It turns out that the type of obj.r.d varies depending on whether your page is using one or multiple device layouts. This property can be either an object or an array.

Seriously, check it out:

This is my page when only the “Default” device has a layout..
experience editor js_ code
..and after a second layout for the “Print” device is added.
experience editor js code

 

That’s why the code from Sitecore support didn’t work for me. That version depends on obj.r.d being an array since it calls obj.r.d.forEach. We typically use a single device layout for our pages (there’s no need for a Print layout since custom print displays can be handled with CSS media queries), so obj.r.d is an object and obj.r.d.forEach is undefined. As a result, the check “if (obj && obj.r && obj.r.d && obj.r.d.forEach)” just fails silently and the dreaded Experience Editor red ribbon of doom appears.

 

Fix – 3rd Time’s A Charm

Here is my version of the fix. It normalizes the obj.r.d property, so it won’t matter how many layouts you have.

postServerRequest: function (requestType, commandContext, handler, async) {

function normalizeDeviceProp(d) {
if (typeof(d) !== "object")
throw new Error("Unexpected presentation details XML: cannot find device property");

if (d instanceof Array)
return d;

var normalized = [];
normalized.push(d);
return normalized;
}

var token = $('input[name="__RequestVerificationToken"]').val();

// Custom Brainjocks code to fix Experience Editor error.
var ajaxData = unescape(JSON.stringify(commandContext));
if (commandContext && commandContext.scLayout) {
var obj = JSON.parse(commandContext.scLayout);
if (obj && obj.r) {
normalizeDeviceProp(obj.r.d).forEach(function (d) {
if (d.r instanceof Array) {
d.r.forEach(function (r) {
var val = r["@par"];
if (val && val.length > 0) {
ajaxData = ajaxData.replace(unescape(val), val);
}
});
}

});
}
}

jQuery.ajax({
url: "/-/speak/request/v1/expeditor/" + requestType,
data: {
__RequestVerificationToken: token,
data: ajaxData
},
success: handler,
type: "POST",
async: async != undefined ? async : false
});
}

 

If you have any feedback or questions on resolving this Experience Editor error, please let me know in the comments. Thanks!

About the Author

More from this Author

Thoughts on “Experience Editor error – After parsing a value an unexpected character was encountered: {. Path ‘scLayout’”

  1. This was a great fix. Haven’t had a chance to look into what Sitecore support actually gave us, but this one worked right away. Thanks!

  2. Great work, this worked perfectly for me in Sitecore 8.2, update 5. Thank you so much for posting your findings!

  3. Thanks for the great post. I did have to make one change to your code for Sitecore 8.2 Update 6. Basically, handling the case were d.r is not an array.

    postServerRequest: function (requestType, commandContext, handler, async) {

    function normalizeDeviceProp(d) {
    if (typeof(d) !== “object”)
    throw new Error(“Unexpected presentation details XML: cannot find device property”);

    if (d instanceof Array)
    return d;

    var normalized = [];
    normalized.push(d);
    return normalized;
    }

    function fixAjaxData(r) {
    var val = r[“@par”];
    if (val && val.length > 0) {
    ajaxData = ajaxData.replace(unescape(val), val);
    }
    }

    var token = $(‘input[name=”__RequestVerificationToken”]’).val();

    // Custom Brainjocks code to fix Experience Editor error.
    var ajaxData = unescape(JSON.stringify(commandContext));
    if (commandContext && commandContext.scLayout) {
    var obj = JSON.parse(commandContext.scLayout);
    if (obj && obj.r) {
    normalizeDeviceProp(obj.r.d).forEach(function (d) {
    if (d.r instanceof Array) {
    d.r.forEach(function (r) {
    fixAjaxData(r);
    });
    } else {
    fixAjaxData(d.r);
    }
    });
    }
    }

    jQuery.ajax({
    url: “/-/speak/request/v1/expeditor/” + requestType,
    data: {
    __RequestVerificationToken: token,
    data: ajaxData
    },
    success: handler,
    type: “POST”,
    async: async != undefined ? async : false
    });
    }

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Subscribe to the Weekly Blog Digest:

Sign Up
Categories