Walkthrough: Creating a view component with custom logic

Abstract

How to create a Sitecore view component with custom logic.

You use view components to render content and to supply data to your view model. View components are more powerful than partial views and model-bound views, because they support C# classes that you can use to implement additional rendering logic. See the Microsoft documentation on ASP.NET Core view components.

Traditional view components do not support model binding, but the Sitecore ASP.NET Rendering SDK provides model binding to the Sitecore Layout Service output.

This walkthrough demonstrates how to use an ASP.NET Core View Component to render Sitecore content, while also adding and invoking custom logic to add data to your view model.

Note

This walkthrough describes how to:

Create the My Service template

The My Service template defines a set of header text fields for the MyService data source.

To create the My Service template:

  1. In the Content Editor, right-click the /sitecore/Templates/Project/MyProject folder and click Insert, New Template.

  2. In the Select name window, in the Name field, enter My Service and click Next.

  3. In the Location window, confirm that the template is created in the path you just chose and click Next and Close. The Content Editor automatically opens the My Service template.

  4. In the My Service template, on the Builder tab, create a section named My Service Template Fields and two fields:

    • DateHeader (Single-Line Text)

    • ValueHeader (Single-Line Text)

  5. Save the My Service template.

Create the MyService JSON rendering

The MyService JSON rendering can render the content of any data source based on the My Service template.

To create the MyService JSON rendering:

  1. In the Content Editor, right-click the /sitecore/Layout/Renderings/Project/MyProject folder and click Insert, Json Rendering.

  2. In the Message window, enter MyService and click OK. The Content Editor automatically opens the MyService JSON rendering.

  3. In the MyService JSON rendering, on the Content tab, in the Editor Options section, configure the following fields:

    • In the Datasource Location field, enter ./.

    • In the Datasource Template field, click Insert link and in the Insert Item window, select /templates/Project/MyProject/My Service and click Insert.

  4. Save the MyService JSON rendering.

Configure the MyProject-main placeholder for the MyService JSON rendering

The MyProject-main placeholder only accepts renderings that you have configured it for.

To configure the MyProject-main placeholder for the MyService JSON rendering:

  1. In the Content Editor, click the /sitecore/Layout/Placeholder Settings/Project/MyProject/MyProject-main placeholder item.

  2. In the MyProject-main placeholder, on the Content tab, in the Data section, above the Allowed Controls field, click Edit.

  3. In the Select Items window, on the Editors tab, in the All pane, click Layout/Renderings/Project/MyProject/MyService and click the blue arrow blue-arrow.png to copy the MyService JSON rendering to the Selected pane. Then click OK.

  4. Save the MyProject-main placeholder.

Publish the MyProject site

To publish the MyProject site:

  1. In the Content Editor, click sitecore/Content/MyProject/Home.

  2. On the Publish tab, click Publish site.

  3. In the Publish Site window, select the Republish check box and click OK.

Add the MyService JSON rendering to the MyProject/Home page

You must add the MyService JSON rendering to the MyProject-main placeholder on the MyProject/Home page and create the MyService data source, before you publish the page to see the output in the rendering host log.

To add the MyService JSON rendering to the MyProject/Home page:

  1. In the Experience Editor, go to the MyProject/Home page.

  2. On the Home tab, click Component and click one of the Add here handlers that let you add a rendering to the MyProject-main placeholder.

    Illustration showing an Add here handle.
  3. In the Select a Rendering window, click My Service and Select.

  4. In the Select the Associated Content window, on the Create New Content tab, in the Name field, enter MyService data source and click OK.

    Note

    You get an Unknown component 'MyService' message until you register MyServiceViewComponent in the Startup class.

  5. Save the MyProject/Home page.

  6. On the Home tab, click Publish.

  7. In the Publish Item window, select the Smart publish and Publish related items check boxes and click Publish.

  8. Visit the rendering host and check that the MyService JSON rendering prints Unknown Component 'MyService'.

  9. In the rendering host log, check that you see the MyService component with the MyService data source ID and the blank header texts in the Sitecore Layout Service response:

    {
      "uid": "efe02844-bd57-4d31-be93-384440aa8d0c",
      "componentName": "MyService",
      "dataSource": "{79F7E3DF-DD72-4575-AFB7-64E174AC6401}",
      "params": {},
      "fields": {
        "DateHeader": {
          "value": ""
        },
        "ValueHeader": {
          "value": ""
        }
      }
    }

Create the IFakeService service interface

The IFakeService service interface defines what FakeService implementations must contain. In a customer solution, you replace this with a service containing real-world business logic.

To create the FakeService interface:

  1. In Visual Studio with administrator privileges, in Solution Explorer, right-click the RenderingHost project and click Add, New Folder. Name the folder Services.

  2. Right-click the RenderingHost/Services folder and click Add, New Item.

  3. In the Add New Item window:

    • In the left pane, click Installed/Visual C#/ASP.NET Core/Code.

    • In the middle pane, click Interface.

    • At the bottom of the window, in the Name field, enter IFakeService.cs and click Add.

  4. In the IFakeService.cs file, replace the content with the following code:

    using System;
    using System.Threading.Tasks;
    namespace MyProject.Services
    {
        public interface IFakeService
        {
            DateTime FakeDate { get; }
            Task<int> GetFakeValueAsync();
        }
    }
  5. Save the IFakeService.cs file.

Create the FakeService service class

The FakeService service class delivers a date and a value for the MyServiceViewComponent class to display under the MyService data source header texts.

To create the FakeService service class:

  1. In Visual Studio, in Solution Explorer, right-click the RenderingHost/Services folder and click Add, New Item.

  2. In the Add New Item window:

    • In the left pane, click Installed/Visual C#/ASP.NET Core/Code.

    • In the middle pane, click Class.

    • At the bottom of the window, in the Name field, enter FakeService.cs and click Add.

  3. In the FakeService.cs file, replace the content with the following code:

    using System;
    using System.Threading.Tasks;
    namespace MyProject.Services
    {
        public class FakeService : IFakeService
        {
            public DateTime FakeDate => DateTime.Now;
            public async Task<int> GetFakeValueAsync()
            {
                return await Task.Run(() => new Random().Next());
            }
        }
    }
    
  4. Save the FakeService.cs file.

Register the FakeService service in the Startup class

Because FakeService is a service, you must register it in the Startup class.

To register the FakeService service in the Startup class:

  1. In Visual Studio, in Solution Explorer, in the RenderingHost project, double-click the Startup.cs file.

  2. In the Startup.cs file, add the MyProject.Services namespace:

    using MyProject.Services;
  3. In the Startup class, in the ConfigureServices method, add FakeService:

    public void ConfigureServices(IServiceCollection services)
    {
      services.AddTransient<IFakeService, FakeService>();
    }
  4. Save the Startup.cs file.

Create the MyServiceModel model

The MyServiceViewComponent view component class combines the MyService data source header texts with the FakeService service date and value fields in the MyServiceModel model.

To create the MyServiceModel model:

  1. In Visual Studio, in Solution Explorer, right-click RenderingHost/Models and click Add, New Item.

  2. In the Add New Item window:

    • In the left pane, click Installed/Visual C#/ASP.NET Core/Code.

    • In the middle pane, click Class.

    • At the bottom of the window, in the Name field, enter MyServiceModel.cs and click Add.

  3. In the MyServiceModel.cs file, replace the content with the following code:

    using System;
    using Sitecore.AspNet.RenderingEngine.Binding.Attributes;
    using Sitecore.LayoutService.Client.Response.Model.Fields;
    namespace MyProject.Models
    {
        public class MyServiceModel
        {
            public TextField DateHeader { get; set; }
            public TextField ValueHeader { get; set; }
            public DateTime ServiceDate { get; set; }
            public int ServiceValue { get; set; }
            [SitecoreContextProperty]
            public bool IsEditing { get; set; }
        }
    }
    

    The DateHeader and ValueHeader properties inherit from IField and are automatically bound to the Sitecore Layout Service response. This is how they get populated with the MyService data source header texts.

    The ServiceDate and ServiceValue properties are populated by the MyServiceViewComponent class from FakeService.

    The IsEditing property is bound to SitecoreContext with the [SitecoreContextProperty] attribute.

  4. Save the MyServiceModel.cs file.

Create the MyServiceViewComponent view component class

Now that you have created the MyService JSON rendering, the FakeService service, and the MyServiceModel model, you can create the MyServiceViewComponent class, which is central to this walkthrough.

In the MyServiceViewComponent class, the FakeService service content is added to the MyServiceModel model content for the MyService/Default view to display. You can add or invoke any custom logic here, and this is what makes view components so powerful.

To create the MyServiceViewComponent class:

  1. In Visual Studio, in Solution Explorer, right-click the RenderingHost project and click Add, New Folder. Name the folder ViewComponents.

  2. Right-click the RenderingHost/ViewComponents folder and click Add, New Item.

  3. In the Add New Item windows:

    • In the left pane, click Installed/Visual C#/ASP.NET Core/Code.

    • In the middle pane, click Class.

    • At the bottom of the window, in the Name field, enter MyServiceViewComponent.cs and click Add.

  4. In the MyServiceViewComponent.cs file, replace the content with the following code:

    using System;
    using System.Threading.Tasks;
    using Microsoft.AspNetCore.Mvc;
    using MyProject.Models;
    using MyProject.Services;
    using Sitecore.AspNet.RenderingEngine.Binding;
    namespace MyProject.ViewComponents
    {
        public class MyServiceViewComponent : ViewComponent
        {
            private readonly IViewModelBinder modelBinder;
            private readonly IFakeService fakeService;
    
            // Use the view component support for dependency injection to inject
            // FakeService and the
            // Sitecore.AspNet.RenderingEngine.Binding.IViewModelBinder service.
            public MyServiceViewComponent(IViewModelBinder modelBinder, IFakeService fakeService)
            {
                this.modelBinder = modelBinder;
                this.fakeService = fakeService;
            }
    
            public async Task<IViewComponentResult> InvokeAsync()
            {
                // Bind MyServiceModel to the Sitecore Layout Service response
                // when the view component is invoked.
                var model = await modelBinder.Bind<MyServiceModel>(this.ViewContext);
    
                if (model.IsEditing)
                {
                    // Set mock values to be displayed in edit mode only.
                    // This avoids invoking FakeService in the Experience Editor and
                    // can be very helpful for content authors, especially if
                    // FakeService requires authentication or the user values are
                    // not available in edit mode.
                    model.ServiceDate = DateTime.MinValue;
                    model.ServiceValue = 42;
                }
                else
                {
                    // Invoke FakeService to populate the date and value of the model.
                    var serviceResult = await fakeService.GetFakeValueAsync();
                    model.ServiceDate = fakeService.FakeDate;
                    model.ServiceValue = serviceResult;
                }
    
                // Return the model to the Default.cshtml Razor view.
                return View(model);
            }
        }
    }
  5. Save the MyServiceViewComponent.cs file.

Create the MyService/Default Razor view

The MyService/Default Razor view binds to the MyServiceModel model and presents the content on the page.

To create the MyService/Default view:

  1. In Visual Studio, in Solution Explorer, right-click the RenderingHost/Views/Shared/Components folder and click Add, New Folder. Name the folder MyService.

    Note

    The MyService folder name must match the MyServiceViewComponent class name but without the ViewComponent suffix. This is how Visual Studio connects the Views/Shared/Components/MyService/Default view to the ViewComponents/MyServiceViewComponent class.

  2. Right-click the RenderingHost/Views/Shared/Components/MyService folder and click Add, New Item.

  3. In the Add New Item window:

    • In the left pane, click Installed/Visual C#/ASP.NET Core/Web.

    • In the middle pane, click Razor View - Empty.

    • At the bottom of the window, in the Name field, enter Default.cshtml and click Add.

  4. In the Default.cshtml file, replace the content with the following code:

    @model MyProject.Models.MyServiceModel
    <h2 asp-for="DateHeader"></h2>
    @Model.ServiceDate.ToString("R")
    <h2 asp-for="ValueHeader"></h2>
    @Model.ServiceValue
  5. Save the Default.cshtml file.

Register the MyServiceViewComponent view component in the Startup class

To use the MyServiceViewComponent view component on a web page, you must register it in the Startup class.

To register the MyServiceViewComponent view component in the Startup class:

  1. In Visual Studio, in Solution Explorer, in the RenderingHost project, double-click the Startup.cs file.

  2. In the Startup.cs file, in the Startup class, in the ConfigureServices method, in the AddSitecoreRenderingEngine service registration, add the MyService view component option:

    services.AddSitecoreRenderingEngine(options =>
    {
      options
        .AddModelBoundView<ContentBlockModel>("ContentBlock")
        .AddViewComponent("MyService")
        .AddDefaultPartialView("_ComponentNotFound");
    })

    Note

    The AddViewComponent parameter must match the MyServiceViewComponent name but without the ViewComponent suffix.

  3. Save the Startup.cs file.

At this point, you can open the MyProject/Home page in the Experience Editor and on the rendering host to see the MyServiceViewComponent view component output. We recommend that you check the rendering host log for errors.

Illustration showing the Experience Editor with the MyServiceViewComponent view component.
Illustration showing the rendering host with the MyServiceViewComponent view component.

The left screenshot shows the Experience Editor with the MyServiceViewComponent view component. The [No text in field] headers reveal that the MyService data source header text properties are not yet populated, and the date and the number 42 confirm that the FakeService service displays mock values in editing mode.

The right screenshot shows the rendering host with the MyServiceViewComponent view component. The empty MyService data source header text properties are not shown, and the date and the random number confirms that the FakeService service displays live values in live mode.

Add content to the MyService data source

To get header texts on the rendering host page, you use the Experience Editor to add content to the MyService data source.

To add content to the MyService data source:

  1. In the Experience Editor, go to the MyProject/Home page.

  2. To insert your own header text values into the MyService data source, click [No text in field].

  3. Save the MyProject/Home page.

  4. On the Home tab, click Publish.

  5. In the Publish Item window, select the Smart publish and Publish related items check boxes and click Publish.

  6. Visit the rendering host to check that you see the MyServiceViewComponent view component with your header text values.

    Illustration showing the rendering host page with the MyServiceViewComponent view component and header texts.

Tip