In this blog-post, we would be looking at how you can create custom Rendering Contents Resolver to customize the rendering output of Sitecore’s Layout Service.
Sitecore’s Layout Service is a Headless endpoint which is responsible for providing data of the requested page or rendering in the form of a JSON object. GraphQL to get the Layout Service is available in both Sitecore Headless (JSS) in traditional Content Delivery and also in Sitecore Experience Edge product. Rendering Content Resolvers when used in combination with Layout Service expose/provide complex Sitecore Content of the rendering again in the form of a JSON Object.
Sitecore Headless provides six rendering contents resolvers, by default, and they are found here: /sitecore/system/Modules/Layout Service/Rendering Contents Resolvers.
- Context Item Children Resolver: resolves/serializes the children of the context item
- Context Item Resolver: resolves/serializes the context item
- Datasource Item Children Resolver: resolves/serializes the children of the rendering’s datasource item
- Datasource Resolver: resolves/serializes the rendering’s datasource item
- Folder Filter Resolver: resolves items of Folder template type. The Template ID is specified in the Item Selector Query field of the resolver item in Sitecore.
- Sitecore Forms Resolver: resolver specific to form items.
These default resolvers address the majority of situations, but while working on a JSS site, there is a significant likelihood that custom resolvers may be required. For example: obtaining the fields and details of a datasource item along with its children in a single JSON object is one highly frequent case which is not supported by any of the resolvers described above.
So, allow me to walk you through this simple process of developing a custom rendering content resolver, which entails:
- Creating the class type where we will implement our own Sitecore content resolution mechanism.
- Creating a Resolver Sitecore Item to allow user to select it from the list of available resolvers.
We will consider Datasource Item with Children Resolver as an example in the detailed process mentioned below.
Creating the class type where we will implement our own Sitecore content resolution mechanism:
The class should inherit the Sitecore.LayoutService.ItemRendering.ContentsResolvers.RenderingContentsResolver and must override ResolveContents method of the base class.
Code snippet of the class (please read the inline comments to know the intent of the code written):
using System.Collections.Generic; using System.Linq; using Newtonsoft.Json.Linq; using Sitecore.Data.Items; using Sitecore.Diagnostics; using Sitecore.LayoutService.Configuration; using Sitecore.LayoutService.ItemRendering.ContentsResolvers; using Sitecore.Mvc.Presentation; namespace Sitecore.Customizations.RenderingContentResolvers { public class DatasourceWithChildrenItemResolver : RenderingContentsResolver { public override object ResolveContents(Rendering rendering, IRenderingConfiguration renderingConfig) { //check if the parameters are not null Assert.ArgumentNotNull(rendering, nameof(rendering)); Assert.ArgumentNotNull(renderingConfig, nameof(renderingConfig)); //get the datasource item Item datasourceItem = this.GetContextItem(rendering, renderingConfig); //return null object if the datasourceItem is null if (datasourceItem == null) return null; //initialize the JSON object to be returned with the datasourceItem details JObject jobject = ProcessItem(datasourceItem, rendering, renderingConfig); //get the children of the datasourceItem IEnumerable<Item> items = GetItems(datasourceItem); List<Item> itemList = items != null ? items.ToList() : null; //return the JSON object if children do not exist if (itemList == null || itemList.Count == 0) return jobject; //add children item details to the JSON object and return the object jobject["items"] = ProcessItems(itemList, rendering, renderingConfig); return jobject; } } }
Creating a Resolver Sitecore Item to allow user to select it from the list of available resolvers:
It is recommended to create the custom rendering resolvers in a separate folder under /sitecore/system/Modules/Layout Service/Rendering Contents Resolvers.
- Create a new folder of /sitecore/templates/System/Layout/Layout Service/Rendering Contents Resolvers Folder type inside Rendering Contents Resolvers using the insert options.
- Create the custom content resolver, again, using the insert options.
- As an example, I created Datasource Item With Children Resolver. Now let’s look at the fields of the resolver items (refer the default content resolver, they are fairly intuitive with the short description provided:
- Type: Put the namespace of the custom resolver class and its assembly like so: Customizations.RenderingContentResolvers.DatasourceWithChildrenItemResolver, Sitecore.Customizations
- Include Server URL in Media URLs: checked by default.
- Use Context Item: this field is unchecked, by default, which means that the resolver will use the datasource item(of the rendering) rather than the Context Item. When it is selected, the JSON object will include route level data. For our example, we will keep it unchecked.
- Item Query Selector: This field allows the user to add queries which can manipulate how the content is being processed. Like for the default folder content resolver, this field contains the ID of the “Folder” item and only those items will be included while processing the Sitecore Content
For our example, we need child items of the datasource, so we will add the query to select the children which is “/*”. All these fields are respected while serializing the rendering data in the resolver.
And your custom rendering contents resolver is ready!
It will be available in the list of resolvers in the Rendering Contents Resolver field of the rendering. With this custom resolver selected, the JSON output will include data of the datasource item along with its children.
I have taken into consideration a very simple example for the sake of simplicity. However, you may come across complex scenarios like including data from multiple sources other than the context/datasource items and its children; it can be incorporated in the ResolveContents method. The current example code returns all the fields of the child items which is an improvement area where you can return just the required fields.
I hope this blog post helps you in your Sitecore Headless journey.
Great Nice Blog.