Data from Custom Controller in Same Format as Layout Service

Layout Service is used in headless Sitecore development to get the content from Sitecore items as JSON. In Sitecore JSS, the usage of Layout Service is related with page rendering, whenever you change the route either on client or with server side rendering, JSS app calls Layout Service passing new URL in ?item= query string parameter. Using JSS SDK in your React, Vue, Angular, or Next application you can leverage this data inside your components by passing props.fields.myfield to components from SDK like <Text field=''/> or <Image field=''/>.

But what if you need to do additional client side’s call to Sitecore to fetch more data after the page is rendered? You would probably create your own MVC Controller, which reads the item and returns necessary data as JSON, which of course make sense.

In this blog I will show how to reuse base Layout Service classes, so your custom controller would return the data in similar way as Layout Service would, so your front-end code should work with this data without too many modifications.


If we decompile Layout Service dlls we can check that in the top layer there is a LayoutServiceController MVC controller which process the items and return it as JSON (internally it calls content resolvers for each rendering used on the page).

We need first to create a service which can serialize Sitecore items using JSSItemSerializer and return it as JObject or JArray, similar to content resolver:

and interface for it:

We can register it in DI:

and config patch:

Finally we can create our base controller, which mimics Layout Service’s Content Resolver functionalities (keep in mind that we can also use same attributes, meaning that client’s will have to pass sc_apikey parameter to call the API):


We can use our base controller like this in custom controller (this sample will return item and subitems for ID passed to the action):

and register it as API route:

with config patch:

Additionally for server side rendering we need to remember to exclude /myapi/ path from SSR, so JSS will not try to call layout service for it, but proxy it directly to Sitecore server.

Now we can call our custom API like this from JSS app:


and results will be similar to what Layout Service would return: