ASP.NET Core Rendering SDK
Utilizing multiple layouts

ASP.NET Core Rendering SDK <br/>Utilizing multiple layouts

Sitecore Headless uses Layout items based on new template - /sitecore/templates/Foundation/JavaScript Services/JSS Layout. This template has “Path” field but it’s value in most cases defaulted to “/Views/JssApp.cshtml“ value. But you may ask how to use multiple layouts with your website, how to differ them? Let’s say, you have website with landing and product pages that has different layout than other pages.

So, have 3 pretty same Layout items that may (or may not) differ with Placeholders field content.

There is pretty easy answer exist - all needed information are passed from Layout Service to Rendering Host’s Controller in Sitecore.LayoutService.Client.Response.Model.Route model.

using Microsoft.AspNetCore.Mvc;
using Sitecore.AspNet.RenderingEngine.Filters;

namespace Rendering.Controllers;

public class SitecoreController : Controller
{
    [UseSitecoreRendering]
    public IActionResult Index(Sitecore.LayoutService.Client.Response.Model.Route route)
    {
        return View(route);
    }
}

It looks like there are couple of ways to select proper view for layout rendering, let’s start with the most safe and straightforward for my opinion:

Based on LayoutId

Since IDs are not changing a lot, it looks like most safe way to implement Layout selector. In our example we have 3 Layout items with different IDs. In each request Route model provides us information about Layout ID used by current item, so, the most obvious way will be to create some static class to store this IDs and use them in code:

namespace Rendering;

public static class LayoutIds
{
    public static readonly string Page = "67275948-A173-48FE-8946-CD6C6C4AB151";
    public static readonly string ProductPage = "73E2BEF2-D8A8-48C0-BC94-F603FDAF37B6";
    public static readonly string LandingPage = "456BF85B-06CE-4CBC-AC27-858BF58E6544";
}

 

Then, in controller’s action all we need is to compare and select needed View file:

using Microsoft.AspNetCore.Mvc;
using Sitecore.AspNet.RenderingEngine.Filters;

namespace Rendering.Controllers;

public class SitecoreController : Controller
{
    [UseSitecoreRendering]
    public IActionResult Index(Sitecore.LayoutService.Client.Response.Model.Route route)
    {
        if (route.LayoutId == LayoutIds.LandingPage)
        {
            return View("LandingPage.cshtml", route);
        }
        return View(route);
    }
}

 

Pros:

  • Coupling to Layout items id looks very confident as there are no straight forward ways to change item ID.

  • Any logic may be used in selecting view, such as using subfolders and other attributes of Route model (DeviceId, ItemLanguage, etc).

Cons:

  • Copying IDs into code

 

Based on TemplateId/TemplateName

There are not only LayoutId field available in Route class, but TemplateId and TemplateName. Using this fields you may implement View selection that finds View based on template. That saves you from hardcoding IDs in code, but may have couple of more serious issues.

Pros:

  • Straightforward View selection based on Template Name

Cons:

  • Changes in item names may require changes in code

  • Every new template will require new View or changes in code