Model binding
Model binding is a standard ASP.NET Core process that maps data from incoming HTTP requests to strongly typed models used in controller actions and views.
Sitecore ASP.NET Core SDK developers use model binding to connect XM Cloud content to their ASP.NET Core application's models. Specifically, to connect the data from the Experience Edge response to strongly typed model objects. For example, you can directly bind a text field named Title
in your XM Cloud content to a string property named Title
in your model.
This makes rendering model-bound views easy, and it allows developers to work with XM Cloud content in a more structured and type-safe manner.
Model binding using the ASP.NET Core SDK
The ASP.NET Core SDK provides ASP.NET Core model binding support for key objects, properties, and fields that Experience Edge returns in a SitecoreLayoutResponse
object.
Model binding is done with Sitecore.AspNetCore.SDK.RenderingEngine.Binding.Attributes
. If a model property is not mapped through attributes, the default ASP.NET Core model binding behavior takes over.
The attributes, sources, and providers are located in the Sitecore.AspNetCore.SDK.RenderingEngine.Binding
namespace.
Model properties that implement IField
do not require explicit attributes. They 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.
Example
Here's an example response from Experience Edge:
{
"sitecore": {
"context": {
"contextproperty1": "",
"contextproperty2": "",
"CustomContextSingleProperty": "",
"CustomContextClass": {
"customcontextprop": ""
}
},
"route": {
"routeproperty1": "",
"routeproperty2": "",
"fields": {
"routefield1": {
"value": ""
}
},
"placeholders": {
"placeholder1": [
{
"componentproperty1": "",
"componentproperty2": "",
"fields": {
"componentfield1": {
"value": ""
}
}
}
]
}
}
}
}
For this response, here's a matching view model class:
using Sitecore.AspNetCore.SDK.RenderingEngine.Binding;
using Sitecore.AspNetCore.SDK.RenderingEngine.Binding.Attributes;
using Sitecore.AspNetCore.SDK.LayoutService.Client.Response;
using Sitecore.AspNetCore.SDK.LayoutService.Client.Response.Model;
using Sitecore.AspNetCore.SDK.LayoutService.Client.Response.Model.Fields;
public class ComplexComponent
{
public SitecoreLayoutResponse Response { get; set; }
// Bind to "context"
public Context Context { get; set; }
// Bind to "contextproperty1". Also binds custom Sitecore "Context" properties.
[SitecoreContextProperty(Name = "contextproperty1")]
public bool ContextProperty1 { get; set; }
// Bind to "contextproperty2". Also binds custom Sitecore "Context" properties
[SitecoreContextProperty(Name = "contextproperty2")]
public bool ContextProperty2 { get; set; }
// Bind to current Sitecore "Context" and all custom context extensions. Inherits "Context" class.
public ContextExt ContextExt { get; set; }
// Bind to current Sitecore "Context" and Custom Sitecore Context Properties and objects.
[SitecoreContext]
public CustomContextClass CustomContextClass { get; set; }
// Bind to "route"
public Route Route { get; set; }
// Bind to "routeproperty1"
[SitecoreRouteProperty(Name = "routeproperty1")]
public string RouteProperty1 { get; set; }
// Bind to "routeproperty2"
[SitecoreRouteProperty(Name = "routeproperty2")]
public string RouteProperty2 { get; set; }
// Bind to "route"."fields"
[SitecoreRouteFields]
public RouteFields RouteFields { get; set; }
// Bind to "routefield1"
[SitecoreRouteField(Name = "routefield1")]
public TextField RouteField1 { get; set; }
// Bind to "componentproperty1"
[SitecoreComponentProperty(Name = "componentproperty1")]
public string ComponentProperty1 { get; set; }
// Bind to "componentproperty2"
[SitecoreComponentProperty(Name = "componentproperty2")]
public string ComponentProperty2 { get; set; }
// Bind to "route"."placeholders"
[SitecoreComponentFields]
public ComponentFields ComponentFields { get; set; }
// Bind to "componentfield1"
[SitecoreComponentField(Name = "componentfield1")]
public TextField ComponentField1 { get; set; }
}
public class RouteFields
{
// Bind to "routefield1"
[SitecoreRouteField(Name = "routefield1")]
public TextField RouteField1 { get; set; }
}
public class ComponentFields
{
// Bind to "componentfield1"
[SitecoreComponentField(Name = "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; }
}