I had a major urge yesterday to continue my tinkering of the Sitecore Item Web API, and wondered how one would go about changing the serialization format of its response.
Without re-reading the documentation on how one could go about doing this — I forgot that this was discussed in its documentation (check out pages 16-17 in the Sitecore Item Web API 1.0.0 Developer’s Guide where you can see how to use an XML serializer) — I tackled this by experimentation, and came up with a slightly different solution than the one offered in the Developer’s Guide.
I considered using an XML serializer for this blog post, but decided to fish around on the internet to see what other data serialization formats exist, and discovered YAML — a format that looks similar to JSON.
I continued my internet surfing — I mean research — and found a .NET library — YamlDotNet — that assists developers in converting objects into YAML, and decided to give it a go.
The following Sitecore item Web API Serializer uses this YAML library:
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using Sitecore.Diagnostics; using Sitecore.ItemWebApi.Serialization; using YamlDotNet.RepresentationModel.Serialization; namespace Sitecore.Sandbox.ItemWebApi.Serialization { public class YamlSerializer : ISerializer { // Serializer in YamlDotNet.RepresentationModel.Serialization private static readonly Serializer Serializer = new Serializer(); public YamlSerializer() { } public string Serialize(object value) { Assert.ArgumentNotNull(value, "value"); string yaml = string.Empty; using(StringWriter stringWriter = new StringWriter()) { Serializer.Serialize(stringWriter, value); yaml = stringWriter.ToString(); } return yaml; } public string SerializedDataMediaType { get { return "application/x-yaml"; } } } }
The Serializer above just delegates responsibility to the YamlDotNet’s YAML serializer.
Now that we have our YamlSerializer ready to go, we have to somehow wire it up to the Sitecore Item Web API.
After some digging in Sitecore.ItemWebApi.dll, I learned the out of the box JsonSerializer is set in a preprocessRequest pipeline processor:
Following this lead, I created a custom preprocessRequest pipeline processor for setting our new YamlSerializer:
using System; using System.Web; using Sitecore.Pipelines.PreprocessRequest; using Sitecore.Diagnostics; using Sitecore.ItemWebApi.Serialization; using Sitecore.Sandbox.ItemWebApi.Serialization; namespace Sitecore.Sandbox.ItemWebApi.Pipelines.PreprocessRequest { public class ResolveSerializer : PreprocessRequestProcessor { public override void Process(PreprocessRequestArgs arguments) { Assert.ArgumentNotNull(arguments, "arguments"); Assert.ArgumentNotNull(arguments.Context, "arguments.Context"); Assert.ArgumentNotNull(arguments.Context.Request, "arguments.Context.Request"); ISerializer serializer = GetSerializer(arguments.Context.Request); if (serializer != null) { Sitecore.ItemWebApi.Context.Current.Serializer = serializer; } } private static ISerializer GetSerializer(HttpRequest request) { if(IsYamlRequest(request)) { return new YamlSerializer(); } return null; } private static bool IsYamlRequest(HttpRequest request) { Assert.ArgumentNotNull(request, "request"); return string.Equals(request["format"], "yaml", StringComparison.CurrentCultureIgnoreCase); } } }
We only set our YamlSerializer when client code requests data to be returned as YAML — this is made known when the client code sets “Yaml” in a HTTP request parameter named “format” (an example of this would be &format=Yaml via a query string).
I then added the new preprocessRequest pipeline processor in \App_Config\Include\Sitecore.ItemWebApi.config, and made sure it’s called right after /configuration/sitecore/pipelines/preprocessRequest/processor[@type=”Sitecore.ItemWebApi.Pipelines.PreprocessRequest.RewriteUrl, Sitecore.ItemWebApi”] — default instances are set here on the Sitecore Item Web API’s Context instance, and we should ensure this object exits before changing properties on it:
<?xml version="1.0" encoding="utf-8"?> <configuration xmlns:patch="http://www.sitecore.net/xmlconfig/"> <sitecore> <pipelines> <!-- there is stuff up here --> <preprocessRequest> <processor type="Sitecore.Sandbox.ItemWebApi.Pipelines.PreprocessRequest.ResolveSerializer, Sitecore.Sandbox" patch:before="processor[@type='Sitecore.Pipelines.PreprocessRequest.CheckIgnoreFlag, Sitecore.Kernel']" /> <processor type="Sitecore.ItemWebApi.Pipelines.PreprocessRequest.RewriteUrl, Sitecore.ItemWebApi" patch:before="processor[@type='Sitecore.Sandbox.ItemWebApi.Pipelines.PreprocessRequest.ResolveSerializer, Sitecore.Sandbox']" /> </preprocessRequest> <!-- and more stuff down here --> </sitecore> </configuration>
After modifying some code in my copy of the console application written by Kern Herskind Nightingale, Director of Technical Services at Sitecore UK — I added &format=yaml as a query string parameter — I invoked it to retrieve an item in my local instance of Sitecore:
As you can see, the response is now in YAML.
If you have any thoughts on this, or have any recommendations on using other serialization formats, please drop a comment.