Or: How Sitecore DMS and Personalization killed the Sitecore.Context.Item. This post is about how to properly ensure that you get data from the correct item when you develop websites that can be personalized.
The Sitecore.Context.Item returns the current item, i.e. the item that corresponds with the URL that the user has entered. Old Sitecore developers like me has been used to adding the fields of a page to the current item, and then accessing these fields directly using the sc:FieldRenderer:
<%@ Register TagPrefix="sc" Namespace="Sitecore.Web.UI.WebControls" Assembly="Sitecore.Kernel" %> <sc:FieldRenderer ID="MyField" runat="server" FieldName="NameOfMyField" />
This approach is no longer a good approach, as the the customer have been given access to DMS and personalization. Now you no longer know if the content that the usercontrol need, is part of the current item, or another item.
Clik here to view.

Personalize the Component
The customer can now acces any component he likes, and use personalization to alter the data source (or even the component itself). This breaks the pattern of assuming that content is part of the current item.
So what can we do?
Before we grab any field, we need to go through these steps:
- Check the datasource of the current sublayout
- If the datasource is set, use the item from the datasource
- If not, use the current item
These 2 extension methods ease the process:
namespace SitecoreExtensions { public static class SublayoutExtensions { public static Item GetDataSourceItem(this Sublayout sublayout) { string dataSource = sublayout.DataSource; if (string.IsNullOrEmpty(dataSource)) return (Item) null; return Context.Database.GetItem(dataSource); } } public static class UserControlExtensions { public static Item GetDataSourceItem(this UserControl control) { Sublayout sublayout = control.Parent as Sublayout; return sublayout == null ? (Item) null : SublayoutExtensions.GetDataSourceItem(sublayout); } public static Item GetDataSourceOrContextItem(this UserControl control) { return UserControlExtensions.GetDataSourceItem(control) ?? Context.Item; } } }
The SublayoutExtensions extend the Sitecore Sublayout. The GetDataSourceItem returns the item that the datasource points at, or null if the datasource is not set.
The UserControlExtensions extend the .NET UserControl (that really is the base of a Sitecore Sublayout). The GetDataSourceOrContextItem returns the datasource item, with a fallback to Sitecore.Context.Item.
To use the method, you must add the function to the item property of the sc:FieldRenderer:
<sc:FieldRenderer ID="MyField" runat="server" FieldName="NameOfMyField" Item="<%# this.GetDataSourceOrContextItem() %>" />
And you must remember to call DataBind().
This pattern is good because you never end up with a NULL item, as sc:FieldRenderer will crash if you feed it with a NULL value in the item property. There is no reason to crash the entire page just because one component is not configured correct.
From code-behind you simply replace Sitecore.Context.Item with this.GetDataSourceOrContextItem:
var text = Sitecore.Context.Item["NameOfMyField"]; // old way var text = this.GetDataSourceOrContextItem()["NameOfMyField"]; // new way
I would not be surprised if Sitecore in the future would build these functions into sc:FieldRenderer, but untill then we have to do it ourselves.
Image may be NSFW.
Clik here to view.
Clik here to view.
