Published Date: 26 January, 2022

In my last blog, I have explained how to setup ASP.Net Rendering SDK on developer machine and configure with your CM website. In this blog, I would explain the ASP.Net Rendering SDK OOTB solution design.

If you open the OOTB solution file, you will get two projects. A) Platform B) RenderingHost

http://www.tekkishare.com

Platform: This is a regular ASP.Net MVC application that should be deploy on CM/CD servers. Here we can put the code that will run on the CM/CD. Usually, you can keep the code related to Layout Service for example extending rendering content resolver or extending layout service code.

RenderingHost: This is a ASP.Net Core 3.1 web application. This is the consumer of the Layout Service. Here you can put your all-front-end code.

Walkthrough of RenderingHost project

You have appsettings.json file that contain the required information to consume Layout Service

"Sitecore":
{

"InstanceUri": "https://sc101sc.dev.local/",
"LayoutServicePath": "/sitecore/api/layout/render/jss",
"DefaultSiteName": "website",
"ApiKey": "{35AEFAA6-75BC-43AB-ABD3-709AD26FDAA2}",
"EnableExperienceEditor": false

}

I believe attributes are self-explanatory.

To read this configuration section, solution has Option Pattern model class.

public class SitecoreOptions
{

public static readonly string Key = "Sitecore";
public Uri InstanceUri { get; set; }
public string LayoutServicePath { get; set; } = "/sitecore/api/layout/render/jss";
public string DefaultSiteName { get; set; }
public string ApiKey { get; set; }
public Uri RenderingHostUri { get; set; }
public bool EnableExperienceEditor { get; set; }
public Uri LayoutServiceUri
{

get
{

if (InstanceUri == null) return null;
return new Uri(InstanceUri, LayoutServicePath);

}

}

}

ASP.Net Core has a Startup.cs or Startup class that read the configuration section using Option Pattern model class. You can check the constructor of this class, you will find the below section.

Configuration = configuration.GetSection(SitecoreOptions.Key).Get();

Layout Service configuration

Now you have your Sitecore settings on memory. Now time comes to define Layout Service. Startup class has a method called ConfigureServices that execute once at the start of the web application. Here we can define the Layout Service.

// Register the Sitecore Layout Service Client, which will be invoked by the Sitecore Rendering Engine.
services.AddSitecoreLayoutService()
// Set default parameters for the Layout Service Client from our bound configuration object.

.WithDefaultRequestOptions(request =>
{

request.SiteName(Configuration.DefaultSiteName)
.ApiKey(Configuration.ApiKey);

})
.AddHttpHandler("default", Configuration.LayoutServiceUri)
.AsDefaultHandler()

Here, you are passing the correct information (Sitecore website name, API key and Layout Service URL) to form the Layout Service URL.

Localization Support

To support localization, you need to inject code on HTTP request pipeline (It execute with every request).

// Enable ASP.NET Core Localization, which is required for Sitecore content localization.

app.UseRequestLocalization(options =>
{
// If you add languages in Sitecore which this site / Rendering Host should support, add them here.

var supportedCultures = new List<CultureInfo> {new CultureInfo(_defaultLanguage)};
options.DefaultRequestCulture = new RequestCulture(_defaultLanguage, _defaultLanguage);
options.SupportedCultures = supportedCultures;
options.SupportedUICultures = supportedCultures;
// Allow culture to be resolved via standard Sitecore URL prefix and query string (sc_lang).

options.UseSitecoreRequestLocalization();

});

You can also add code for robot detection:

// Enable proxying of Sitecore robot detection scripts

app.UseSitecoreVisitorIdentification();

Handling HTTP request/Page Request

There is a DefaultController available in the solution to resolve all your Sitecore pages. It does not have any constructor and I believe you can't add it otherwise it would not work.

There is an Index action define that take one parameter of PageModel

http://www.tekkishare.com

PageModel class is available inside the Models folder. You can customize it based on the fields available for the page in CMS.

You can see that action method Index is decorated with "UseSitecoreRendering" attribute that is responsible for making a call to the layout service. You can get the response of the Layout Service API using below statement:

HttpContent.GetSitecoreRenderingContext()

This action method called the View available at ~/View/Default/Index.cshtml

http://www.tekkishare.com

If you can see carefully, you will get that the name of the placeholder is aspnetheadless-main (<solutionname>-main). After creating placeholder, you also need to allow all the feature/component those you would like to use.

It means, you must need to create a placeholder with this name in your Sitecore instance and use the same on Page Layout. After adding this placeholder on the page layout, you can see your component placed on the page in the layout service as well.

http://www.tekkishare.com

Mapping components/rendering

We need to tell the SDK client application that what all reusable component (rendering in Sitecore) we have created and using on this application on the pages.

Since it is a onetime activity, we can add this in ConfigureService method of Startup class using AddSitecoreRenderingEngine.

// Register the Sitecore Rendering Engine services.
services.AddSitecoreRenderingEngine(options =>
{
//Register your components here

options
.AddModelBoundView<ContentBlockModel>("ContentBlock")
.AddDefaultPartialView("_ComponentNotFound");
})

Here, "ContentBlock" is the name of the reusable component and ContentBlockModel is the model class. All the Sitecore fields values of the datasource items will be available on the Model object on its respective view.

Your view for each of the component should be available inside the Views/Shared/Components/SitecoreComponent/

http://www.tekkishare.com

http://www.tekkishare.com

Here, you can see that your component is rendering



Happy learning...



References: