Model binding

Version: 22.x
Important

If you integrated your ASP.NET Core app before September 2024, it's using the legacy ASP.NET Core Rendering SDK, version 22 or earlier. This SDK is no longer receiving updates, so we recommend that you upgrade to the latest version of the new ASP.NET Core SDK.

The Sitecore Rendering Engine provides ASP.NET model binding support for key objects, properties, and fields returned by the Layout Service in a SitecoreLayoutResponse object.

Model binding is done with IFieldReader and is case-sensitive. If a model property is not mapped through attributes, default ASP.NET Model-View-Controller model binding behavior takes over.

The attributes, sources, providers, and so on are located in the Sitecore.AspNet.RenderingEngine.Binding namespace of the Rendering Engine libraries.

Model properties that implement IField do not require explicit attributes and bind to the current component or the current route field of the same name.

The current component, response, or route refers to the corresponding objects in the SitecoreLayoutResponse instance that are available as context information on the HttpContext object. For a given request, the current response and route are the same for all components, but the placeholder tag helper sets the current component dynamically.

An example Layout Service response:

RequestResponse
{
  "sitecore": {
    "context": {                               // context
      "contextproperty1": "",                  // context property
      "contextproperty2": "",                  // context property
      "CustomContextSingleProperty": "",       // custom single context property
      "CustomContextClass": {
        "customcontextprop": "",               // custom context property of custom context class
      },
    },
    "route": {                                 // route
      "routeproperty1": "",                    // route property
      "routeproperty2": "",                    // route property
      "fields": {                              // route fields
        "routefield1": {                       // route field
          "value": ""
        }
      },
      "placeholders": {                        // route placeholders
        "placeholder1": [                      // route placeholder
          {
            "componentproperty1": "",          // component property
            "componentproperty2": "",          // component property
            "fields": {                        // component fields
              "componentfield1": {             // component field
                "value": ""
              }
            }
          }
          ]
        }
    }
  }
}

A matching view model class:

RequestResponse
using Sitecore.AspNet.RenderingEngine.Binding;
using Sitecore.AspNet.RenderingEngine.Binding.Attributes;
using Sitecore.LayoutService.Client.Response;
using Sitecore.LayoutService.Client.Response.Model;
using Sitecore.LayoutService.Client.Response.Model.Fields;

public class ComplexComponent
{
  public SitecoreLayoutResponse Response {get; set;}

  public Context Context {get; set;}                            // Bind to "context"

  [SitecoreContextProperty(Name = "contextproperty1")]          // Bind to "contextproperty1". Also binds custom Sitecore "Context" properties.
  public bool ContextProperty1 { get; set; }

  [SitecoreContextProperty(Name = "contextproperty2")]          // Bind to "contextproperty2". Also binds custom Sitecore "Context" properties.
  public bool ContextProperty2 { get; set; }
  
  public ContextExt ContextExt { get; set; }                    // Bind to current Sitecore "Context" and all custom context extensions. Inherits "Context" class.

  [SitecoreContext]                                             // Bind to current Sitecore "Context" and Custom Sitecore Context Properties and objects.
  public CustomContextClass CustomContextClass { get; set; } 

  public Route Route {get; set;}                                // Bind to "route"

  [SitecoreRouteProperty(Name = "routeproperty1")]              // Bind to "routeproperty1"
  public string RouteProperty1 { get; set; }

  [SitecoreRouteProperty(Name = "routeproperty2")]              // Bind to "routeproperty2"
  public string RouteProperty2 { get; set; }

  [SitecoreRouteFields]                                         // Bind to "route"."fields"
  public RouteFields RouteFields { get; set; }

  [SitecoreRouteField(Name = "routefield1")]                    // Bind to "routefield1"
  public TextField RouteField1 { get; set; }
  

  [SitecoreComponentProperty(Name = "componentproperty1")]      // Bind to "componentproperty1"
  public string ComponentProperty1 { get; set; }

  [SitecoreComponentProperty(Name = "componentproperty2")]      // Bind to "componentproperty2"
  public string ComponentProperty2 { get; set; }

  [SitecoreComponentFields]                                     // Bind to "route"."placeholders"
  public ComponentFields ComponentFields { get; set; }

  [SitecoreComponentField(Name = "componentfield1")]            // Bind to "componentfield1"
  public TextField ComponentField1 { get; set; }
}

public class RouteFields
{
  [SitecoreRouteField(Name = "routefield1")]                    // Bind to "routefield1"
  public TextField RouteField1 { get; set; }
}

public class ComponentFields
{
  [SitecoreComponentField(Name = "componentfield1")]            // Bind to "componentfield1"
  public TextField ComponentField1 { get; set; }
}

// A class to extend the current Sitecore "Context" with custom properties
public class ContextExt:Context
{
  public CustomContextClass CustomContextClass { get; set; }
  public string CustomContextSingleProperty { get; set; } 
}

// A class for custom Context properties
public class CustomContextClass
{
  public string CustomContextProp { get; set; }
}
Note

For an example of a context extension, see Extending Context Data Returned by the Layout Service.

Do you have some feedback for us?

If you have suggestions for improving this article,