With the release of Sitecore 7.5, Sitecore’s core product ships with the SPEAK framework. A dependency for SPEAK components is Sitecore.Services.Client, a REST API exposing Sitecore content for consuming applications. While the main consumer of this service are applications built with the SPEAK framework, developers can leverage this service for other non back-end applications.
While you can use Sitecore.Services.Client for public facing applications, there are certain risks that should be considered (which could be a post by itself). The goal of this post is to document an experiment in extending the existing functionality of the service to expose related content.
The approach detailed within the post is purely experimental. Similar approaches should only be considered if validated against all other avenues for using Sitecore as a service. Consider ASP.NET MVC controller actions through attribute routing or implementing a custom ASP.NET Web API solution for CRUD operations.
Obtaining Item References
The default implementation exposes content as JSON through a REST API where you can obtain content by:
1. Item ID
2. Item Path
The resulting JSON returns a set of data inclusive of standard Sitecore system related fields and custom template fields. For item referencing fields, a pipe-delimited list of ids is returned by the service rather than the related item’s content. Having to obtain all content for a particular item and all of its related content requires multiple calls to the API.
For example, consider the following API call and its response:
Notice how the multilist field “Relationship” outputs the item reference ids and not the actual content. To obtain the related item content, we would have to invoke the service for each item reference in the API response.
In order to include related content in our response, we’ll have to override Sitecore’s default implementation.
We can do this by taking the following actions:
1. Define our own Model Factory for the response
2. Create our own Handler Provider to resolve the model factory
3. Wire it all up through dependency injection
4. Ninject.Web.WebApi (DI for this example)
We’ll need a model factory to read in the related item content and append a new field to the ItemModel object. The ItemModel itself is a dictionary of key/value pairs where the key is the field name and the value is the field value. Adding a new field to our model is simple enough as we don’t have to extend the model itself. It already supports dynamically adding fields and their values.
The create method below iterates over each field and performs a lookup for related content items via ExpandReferencedItems. The resulting array of items are then added to a new field RelationshipItems within our ItemModel.
It’s important we add a new field to the model as opposed to editing the existing field. We can’t assume any SPEAK application dependencies can properly consume and parse an array of item content instead of the default pipe-delimited format.
With the Model Factory in place, we’ll next need a Handler Provider to explicitly use the factory when requests are received for item lookup by id, path or by child item.
We then bind our new handler provider to Sitecore’s IHandlerProvider.
The RelationshipItems field now displays all related content, eliminating the need for multiple Web API calls.