Since Sitecore 7 and MVC there is a problem with JSON-Serialization, if you use aliases and set the data source to a folder with a large amount of items (in my case approx. 2000 items).
I can’t switch to item buckets at the moment, because a console application fetches products from a customer url , create items and push them to a Sitecore data storage.
If you want to add a new alias and choose a linked item, nothing happened. A short view in console reveals the problem:
Object {statusCode: 500, error: Object} error: Object message: "Error during serialization or deserialization using the JSON JavaScriptSerializer. The length of the string exceeds the value set on the maxJsonLength property." __proto__: Object statusCode: 500
–
Hmmmkay! Almighty Google has a lot of hits if you search for the problem, up to custom JsonValueProvider or configuration examples, but none of them worked for me. Together with Sitecore support we found a solution for that: A custom JsonSerializer, a PreprocessRequest-Pipeline and a .config-file which should be placed in App_Config/Include. Here is the code:
JsonSerializer
using System; using System.Globalization; using System.Web.Script.Serialization; using Sitecore.Configuration; using Sitecore.Diagnostics; using Sitecore.ItemWebApi.Serialization; namespace SitecoreContrib.Serialization { public class JsonSerializer : ISerializer { public string SerializedDataMediaType { get { return "application/json"; } } public string Serialize(object value) { Assert.ArgumentNotNull(value, "value"); var scriptSerializer = new JavaScriptSerializer { MaxJsonLength = 2097152 }; var setting = Settings.GetSetting("JsonSerialization.MaxLength"); int result; if (!string.IsNullOrEmpty(setting) && !scriptSerializer.MaxJsonLength.ToString(CultureInfo.InvariantCulture).Equals(setting, StringComparison.InvariantCultureIgnoreCase) && int.TryParse(setting, out result)) { scriptSerializer.MaxJsonLength = result; } return scriptSerializer.Serialize(value); } } }
–
The PreprocessRequest-Pipeline
using System; using System.Web; using Sitecore.Diagnostics; using Sitecore.ItemWebApi; using Sitecore.Pipelines.PreprocessRequest; using Sitecore.Support.ItemWebApi.Serialization; using Sitecore.Text; using Sitecore.Web; namespace SitecoreContrib.Serialization.Pipelines.PreprocessRequest { public class RewriteUrl { public virtual void Process(PreprocessRequestArgs arguments) { Assert.ArgumentNotNull(arguments, "arguments"); try { var localPath = arguments.Context.Request.Url.LocalPath; if (!localPath.StartsWith("/-/item/")) { return; } var context = new Sitecore.ItemWebApi.Context { Serializer = new JsonSerializer(), Version = GetVersion(localPath) }; Sitecore.ItemWebApi.Context.Current = context; Rewrite(arguments.Context); } catch (Exception ex) { Logger.Error(ex); } } private static int GetVersion(string path) { Assert.ArgumentNotNull(path, "path"); var str = path.TrimStart(new char[1] {'/'}).Split(new char[1] {'/' })[2]; Assert.IsTrue(str.StartsWith("v"), "Version token is wrong."); int result; Assert.IsTrue(int.TryParse(str.Replace("v", string.Empty), out result), "Version not recognized."); return result; } private static void Rewrite(HttpContext context) { Assert.ArgumentNotNull(context, "context"); var url = context.Request.Url; var strArray1 = url.LocalPath.TrimStart(new char[1] {'/'}).Split(new char[1] {'/'}); var length = strArray1.Length - 3; var strArray2 = new string[length]; Array.Copy(strArray1, 3, strArray2, 0, length); var str1 = string.Format("/{0}", string.Join("/", strArray2)); var str2 = url.Query.TrimStart(new char[1] {'?'}); WebUtil.RewriteUrl(new UrlString { Path = str1, Query = str2 }.ToString()); } } }
–
The .config-file
<?xml version="1.0" encoding="utf-8"?> <configuration xmlns:patch="http://www.sitecore.net/xmlconfig/" xmlns:set="http://www.sitecore.net/xmlconfig/set"> <sitecore> <pipelines> <initialize> <processor type="Sitecore.Pipelines.Loader.ShowVersion, Sitecore.Kernel"> <assemblies> <assembly id="SitecoreContrib.Serialization">/bin/SitecoreContrib.Serialization</assembly> </assemblies> </processor> </initialize> <preprocessRequest> <processor type="SitecoreContrib.Serialization.Pipelines.PreprocessRequest.RewriteUrl, SitecoreContrib.Serialization" patch:instead="*[@type='Sitecore.ItemWebApi.Pipelines.PreprocessRequest.RewriteUrl, Sitecore.ItemWebApi']" /> </preprocessRequest> </pipelines> <settings> <!-- JsonSerialization.MaxLength Specifies the maximum length of JSON strings which can be serialized by the JsonSerializer. Value is specified in bytes. Default value: 2097152 (2 MB) --> <setting name="JsonSerialization.MaxLength" value="2147483647" /> </settings> </sitecore> </configuration>
–
Gotcha! From now you can configure the maxJsonLength-property for your needs.
Happy coding!
Best regards Dirk