Back to home

Creating a Component with Custom Rendering Content Resolver in Sitecore 10 Headless Development

In this article, let us see how we will be a creating a simple AuthorGrid component in Sitecore 10. Till the introduction of Sitecore10, creating a component in Sitecore mostly will be a type of View rendering or a Controller rendering component that follows .NET MVC.

I have created a sitecore site that resembles the SUGCON2022 official website https://europe.sugcon.events/ for demo purpose.

Why do we need a Custom Content Resolvers

In some scénarios the data will not be coming from the rendering data sources or the context items. So we need to somehow return the data to the LayoutService

We also need to process the datasources in custom manner to feed the datasources to the current rendering. In these scenarios the Custom Content Resolvers will come into play.

Basic step create a Custom Content Resolvers

  • CustomContentResolver class has to be created
  • Need to assign this to the Rendering Contents Resolver in Sitecore
  • And then this rendering contents resolver will be mapped in the JsonRendering

The custom content resolvers must be inherited from the parent class RenderingContentsResolver.

Let us see how to create Custom Components with CustomContentResolver in detail

My local environment is having two sites. By default the asp.net rendering host will not be supporting multisites. In order to achieve this you need to tweak a bit which you can refer from a very good post from Ram.

Creating the template

I have created below templates with basic fields like AuthorName, DisplayPicture etc., with respective datasources.

Creating a Custom Rendering Contents Resolver

For the Headless development with dotnet core, one of the main piller is the SitecoreLayoutService. SitecoreLayoutService is the key that serves the layout details of the page in JSON format that can be consumed by the rendering host. You can find the more details about it from my previous post.

So here our content structure will be looking like below. As its a AuthorGrid, we need to resolve the content manually using the custom content resolvers and respond them as part of the layout response.

Let us create a new project like below for the custom content resolver. The structure looks like below,

Creating the Model based on the template

I have created two models Author and Authors for our scenario. Authors.cs is the class that contains List

using Sitecore.Data.Fields;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace Mvp.Feature.AuthorsRH.Models
{
public class Author
{
public string Name { get; set; }
public string ProfilePicture { get; set; }
public string ShortNote { get; set; }
public string Description { get; set; }
}
}
view raw Author.cs hosted with ❤ by GitHub

Next one is the Authors.cs file

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace Mvp.Feature.AuthorsRH.Models
{
public class Authors
{
public IList AllAuthors { get; set; }
}
}
view raw Authors.cs hosted with ❤ by GitHub

Creating the Services

The below set of code is responsible of generating the authorlist which will be part of the layout response. It will read the children items from the datasource of the rendering and it returns the author list. If you look at the below code, it will be easily understandable. We have simply created some service classes and register them as a service.

using Mvp.Feature.AuthorsRH.Models;
using Sitecore.Abstractions;
using Sitecore.Data.Fields;
using Sitecore.Data.Items;
using Sitecore.Links.UrlBuilders;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Web;
namespace Mvp.Feature.AuthorsRH.Services
{
public class AuthorsBuilder : IAuthorsBuilder
{
protected readonly BaseLinkManager LinkManager;
protected readonly BaseMediaManager MediaManager;
public AuthorsBuilder(BaseLinkManager linkManager, BaseMediaManager mediaManager)
{
Debug.Assert(linkManager != null);
LinkManager = linkManager;
MediaManager = mediaManager;
}
public List GetAuthors(Item contextItem)
{
Debug.Assert(contextItem != null);
var items = new List();
items.AddRange(contextItem.Children.Where(item => item.DescendsFrom(Templates.Authors.Id)));
List authorlist = new List();
foreach (var item in items)
{
string imgTag = string.Empty;
ImageField imageField = item.Fields[Templates.Authors.Fields.DisplayPicture];
if (imageField != null && imageField.MediaItem != null)
{
MediaItem image = new MediaItem(imageField.MediaItem);
string src =
Sitecore.Resources.Media.MediaManager.GetMediaUrl(image, new MediaUrlBuilderOptions()
{
AlwaysIncludeServerUrl = true
});
imgTag = String.Format(@"", src, image.Alt);
}
authorlist.Add(new Author()
{
Description = item.Fields[Templates.Authors.Fields.Description].Value,
Name = item.Fields[Templates.Authors.Fields.Name].Value,
ShortNote = item.Fields[Templates.Authors.Fields.ShortNote].Value,
ProfilePicture = imgTag
});
}
return authorlist;
}
}
}
http://www.sitecore.net/xmlconfig/">
using Mvp.Feature.AuthorsRH.Models;
using Sitecore.Data.Items;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace Mvp.Feature.AuthorsRH.Services
{
public interface IAuthorsBuilder
{
List GetAuthors(Item contextItem);
}
}
using Microsoft.Extensions.DependencyInjection;
using Sitecore.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace Mvp.Feature.AuthorsRH
{
public class ServicesConfigurator : IServicesConfigurator
{
public void Configure(IServiceCollection serviceCollection)
{
serviceCollection.AddTransient();
}
}
}

Creating the Rendering Content Resolvers and the Json Rendering

Above we have seen how to created the custom content resolver code and we have to add them in the sitecore as below with correct assembly.

The custom content resolvers to be registered in the path “/sitecore/system/Modules/Layout Service/Rendering Contents Resolvers/”

Json Rendering is as below and have to map the Rendering Contents Resolver in the Layout service section.

Once this is done and if we look at the json response of the layout service of a page item which is having this particular component, we can notice that the LayoutService response data will be having the data which gets resolved by our CustomContentResolver like below.

Creation of the Rendering Host project for the Authors Grid Component

To the Mvp solution, we will be creating a new project for this AuthorsGrid component as Mvp.Feature.Authors.Rendering where we will be registering the view and the model.

The follwing model will be created for this.

using System;
using System.Collections.Generic;
using System.Text;
namespace Mvp.Feature.Authors.Rendering.Models
{
public class Author
{
public string Name { get; set; }
public string ProfilePicture { get; set; }
public string ShortNote { get; set; }
public string Description { get; set; }
}
}
view raw Author.cs hosted with ❤ by GitHub
using Sitecore.AspNet.RenderingEngine.Binding.Attributes;
using System;
using System.Collections.Generic;
using System.Text;
namespace Mvp.Feature.Authors.Rendering.Models
{
public class Authors
{
[SitecoreComponentField]
public Author[] AllAuthors { get; set; }
}
}
view raw Authors.cs hosted with ❤ by GitHub

Registering the ViewComponent. We will be using the .AddModelBoundView() method to register this view component. Please make sure the component name is same as what you have given the Rendering item. In this case its “AuthorsGrid” and along with the model.

using Sitecore.AspNet.RenderingEngine.Configuration;
using Sitecore.AspNet.RenderingEngine.Extensions;
using System;
using System.Collections.Generic;
using System.Text;
namespace Mvp.Feature.Authors.Rendering.Extension
{
public static class RenderingEngineOptionsExtension
{
public static RenderingEngineOptions AddFeatureAuthors(this RenderingEngineOptions options)
{
options.AddModelBoundView("AuthorsGrid");
return options;
}
}
}
@model Authors
    @foreach (var author in Model.AllAuthors)
    {
  • @Html.Raw(author.ProfilePicture)

    @author.Name

    @author.ShortNote

    @author.Description

    }

    Also please make sure to register the component in the Startup.cs for the dotnetcore rendering host project as below.

    Demo

    This compoent is configured in a page item like below and the data source is set to the Authors template root item like below.

    The site is hosted in the netlify cdn and the below is the page that uses the component.

    https://quirky-albattani-641e70.netlify.app/en/speakers