A work colleague and I had a certification for Sitecore DMS. NET Developer (DND) today. The certification was held by Andreas Schmidt and was (as always) very revealing. Once I have further deepened the practices, I’m looking forward to showing you new interesting aspects of Sitecore. 😉
Sitecore 7, MVC, JSON-Serialization and maxJsonLength
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
Sitecore and Bundling
A short note on Sitecore and Bundling.
If you use Bundling within your WebApplication you will maybe wondering why your Script and css files not rendered properly:
Failed to load resource: the server responded with a status of 404 (Not Found) http://YourDomain/sitecore/service/notfound?item=%2fbundles%2fmodernizr&user=sitecore%5cadmin&site=YourSiteName
or
Failed to load resource: the server responded with a status of 404 (Not Found) http://YourDomain/sitecore/service/notfound?item=%2fcontent%2fcss&user=sitecore%5cadmin&site=YourSiteName
–
Sitecore tries to resolve your Bundles as an item. But you can get rid of this with a simple setting adjustment in web.config.
<setting name="IgnoreUrlPrefixes" value="/sitecore/default.aspx|/trace.axd|/webresource.axd|/sitecore/shell/Controls/Rich Text Editor/Telerik.Web.UI.DialogHandler.aspx|/sitecore/shell/applications/content manager/telerik.web.ui.dialoghandler.aspx|/sitecore/shell/Controls/Rich Text Editor/Telerik.Web.UI.SpellCheckHandler.axd|/Telerik.Web.UI.WebResource.axd|/sitecore/admin/upgrade/|/layouts/testing" />
–
Here we go! Just add your bundle-urls pipe-separated to the IgnoreUrlPrefixes-value
<setting name="IgnoreUrlPrefixes" value="/sitecore/default.aspx|/trace.axd|/webresource.axd|/sitecore/shell/Controls/Rich Text Editor/Telerik.Web.UI.DialogHandler.aspx|/sitecore/shell/applications/content manager/telerik.web.ui.dialoghandler.aspx|/sitecore/shell/Controls/Rich Text Editor/Telerik.Web.UI.SpellCheckHandler.axd|/Telerik.Web.UI.WebResource.axd|/sitecore/admin/upgrade/|/layouts/testing|/bundles|/Content/css" />
–
Best practise:
It’s highly recommended to patch such Settings in your own Settings.config-file in App_Config/Include-Folder like this:
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
<sitecore>
<settings>
<!-- IGNORE URLS
Set IgnoreUrlPrefixes to a '|' separated list of url prefixes that should not be
regarded and processed as friendly urls (ie. forms etc.)
-->
<setting name="IgnoreUrlPrefixes">
<patch:attribute name="value">/sitecore/default.aspx|/trace.axd|/webresource.axd|/sitecore/shell/Controls/Rich Text Editor/Telerik.Web.UI.DialogHandler.aspx|/sitecore/shell/applications/content manager/telerik.web.ui.dialoghandler.aspx|/sitecore/shell/Controls/Rich Text Editor/Telerik.Web.UI.SpellCheckHandler.axd|/Telerik.Web.UI.WebResource.axd|/sitecore/admin/upgrade/|/layouts/testing|/bundles|/Content/css</patch:attribute>
</setting>
</settings>
</sitecore>
</configuration>
Everything is a…
Everything is an item.
Welcome to Seiten.Kern
Let me guess you think: WTF is Seiten.Kern! Of course you did am I right? 😉
Seiten.Kern is a funny german translation for Sitecore, nothing more.
With this Blog I want to share experience in web development with Sitecore CMS, also share Code Snippets, How-to’s, Best practises and more.
I hope you find usefull informations here and maybe I can get you a bit deeper in Sitecore development.
Have fun!
Best regards Dirk