Unable to serialize the session state. In ‘StateServer’ and ‘SQLServer’ mode

When switching the sessionState mode of your web project from InProc to SQLServer you might encounter this error:

Exception: System.Web.HttpException
Message: Unable to serialize the session state. In ‘StateServer’ and ‘SQLServer’ mode, ASP.NET will serialize the session state objects, and as a result non-serializable objects or MarshalByRef objects are not permitted. The same restriction applies if similar serialization is done by the custom session state store in ‘Custom’ mode.

.NET handles the storage of session objects differently from InProc to SQLServer. When storing session objects in a SQL Server, .NET will serialize the objects. This is necessary because the session object needs to be transferred from server to server.

To support this, all you need is to mark the objects that are part of your sessions with the [Serializable]  attribute:

namespace MyNameSpace
  // Class is marked as serializable
  public class MyClass
    // Some code here

So how do you find the classes that need the [Serializable] attribute?

.NET is pretty good at telling which classes needs to be serializable in the nested exception:

Nested Exception

Exception: System.Runtime.Serialization.SerializationException
Message: Type ‘MyNamespace.MyClass‘ in Assembly ‘MyAssembly, Version=, Culture=neutral, PublicKeyToken=null’ is not marked as serializable.
Source: mscorlib



Sitecore does not as such support other modes than InProc session state. As Sitecore states (quote from the Sitecore Scaling Guide):

The Sitecore CMS user interfaces require in-process ASP.NET session management. For CM
instances, the value of the mode attribute of the /configuration/system.web/sessionState
element in the web.config file must be InProc.
In-process session management requires you to configure the CM load balancer for server affinity —
also known as sticky sessions. You can use other values for the mode attribute in the CD

This means that the Sitecore client and page editor is not tested using other session state methods than InProc. But since the content delivery servers do not touch the Sitecore UI, it is up to you to make the front end code compatible with StateServer or SQLServer methods.

The best session state management for Sitecore CD servers would still be InProc, and let your load balancer use sticky sessions.

Posted in c#, General .NET, Sitecore | Tagged , , , , , , | 1 Comment

Stream Sitecore media items to HttpResponse

Here is a small tip for you who is doing API’s based on Sitecore. How to get an item from the Sitecore Media Library and stream it to the HttpResponse of a page.

This is an example of an .ashx HttpHandler class that gets the ID of an Sitecore Media Library item and streams the item. Add your own exception handling as you wish.

using System;
using System.Net;
using System.Web;
using Sitecore.Data.Items;
using Sitecore.Diagnostics;
using Sitecore.Configuration;

namespace MyProject
  public class GetImage : IHttpHandler
    public void ProcessRequest(HttpContext context)
      // ID of media item
      string id = context.Request.QueryString["id"];

      // Get media item
      MediaItem item = (MediaItem)Factory.GetDatabase("web").GetItem(id);

      // Get name to be shown when image is saved
      string imageName = item.Name + "." + item.Extension;

      context.Response.ContentType = mediaItem.MimeType;
      context.Response.AppendHeader("Content-Disposition", string.Format("inline;filename=\"{0}\"", imageName));
      context.Response.StatusCode = (int)HttpStatusCode.OK;
      context.Response.BufferOutput = true;
      // Copy the media stream to the response output stream
      // As momma always said: Always remember to flush

    public bool IsReusable
        return false;

The trick lies within the type casting of an Item to a MediaItem. The MediaItem contains a media stream that can be copied to the OutputStream of the HttpResponse.

Another trick is to construct a file name from the item name + the file extension found on the MediaItem. Adding this to the output stream will make the name appear as the default file name when users saves your file.

Posted in .net, c#, Sitecore 7 | Tagged , , , | Leave a comment

Sitecore Code Generator and O/R mapper

You probably have never used a code generator for the same reason I never used a code generator:

  • It was not developed by yourself
  • It’s not generating the code you need
  • You cannot extend it with the stuff you need
  • They create the same code for all of your Sitecore templates
  • It’s difficult to install
  • It was not developed by yourself.

A code generator that creates an O/R relationship between your Sitecore templates and your code can save you a ton of work though:

  • Automatically update your code when new templates are created
  • There is never any mismatch between your code and Sitecore templates
  • Code class names matches Sitecore template names
  • All field names are mapped correctly

That is why I introduce the open-source, freeware, use-as-you-please:

SITECOREORM, The object/relational code generator for Sitecore.

You can download it here for free, including the source code:

SitecoreORM O/R Mapper and Code Generator



The SitecoreORM is a code generator framework that allows you to create code templates based on well-known user controls (.aspx) pages, and generate code from all of your Sitecore templates.

There is no Sitecore package; all you do is to place the code in your solution and call \sitecore modules\Shell\SitecoreORM\Execute.aspx to execute the code generation.

Out of the box, SitecoreORM generates simple classes that maps all fields on a Sitecore template, references to inherited templates, and a static struct of field names to be used by Sitecore’s sc:FieldRenderer.

But the idea behind SitecoreORM is that you define yourself how your classes should look like.

Changing the output is done by simply changing some .aspx pages. For example, the code template is an .aspx page. This is an example of how it looks (simplified, download the code for the complete example):

namespace <%# Namespace %>
  public class <%# ClassName %> : BaseItem
    public <%# ClassName %>(Item innerItem)
      InnerItem = innerItem;

    public Item InnerItem { get; private set; }

    public override FieldCollection Fields
      get { return InnerItem.Fields; }

    #region Inherited Templates
<%# ExecuteCodeProvider("SomeClass, SomeDll", "SomeParameter") %>

Generating fields, inherited templates or other thing you need, is done using code providers, that you plug in. SitecoreORM uses reflection to find the code, and your class only needs to implement an ICodeProvider interface that has 1 method: Get().

Here is an example of an .aspx file that generates a Sitecore field (a CheckBox field):

<%@ Page Language="C#" AutoEventWireup="true" %>
<%@ Import Namespace="Sitecore.Data.Items" %>
<%@ Import Namespace="SitecoreORM.CodeProviders" %>
<%@ Import Namespace="SitecoreORM.Services" %>
<script runat="server">

  void Page_Load(object sender, System.EventArgs e)

  private TemplateFieldItem Field
    get { return GenerateFieldProperties.Field; }

  private string PropertyName
    get { return NameNormalizerService.GetValidName(Field.Name); }


    /// <summary>
    /// <%# TemplateFieldItemCommentService.GetComment(Field) %>
    /// </summary>
    public Sitecore.Data.Fields.CheckboxField <%# PropertyName %>
      get { return InnerItem.Fields["<%# Field.Name %>"]; }

The SitecoreORM framework is written with the fewest lines of code that will do the job. The code is as simple as possible, making it easier to extend, and for you to understand.

Features of SitecoreORM includes:

  • O/R mapping Sitecore templates to C# code.
  • Every aspect of the code generation can be customized:
    • .aspx page based code generation allows you to choose the class format yourself.
    • Each field type from Sitecore can be mapped by .aspx pages, making it easy to determine how each field type from Sitecore should be mapped.
    • Inherited templates can be mapped as well.
    • Field names can be mapped to be used by sc:FieldRenderer
    • Plug in your own code; SitecoreORM uses reflection to find the code generators.
  • Customizable output using an include file (/app_config/include/sitecoreorm.config)
    • Determine class name suffixes
    • Determine name space prefixes
    • Determine removing of parts of template path from namespace
    • Determine file destination for generated classes
    • Specify which template folders to ignore (for example /system/ and /common/)
    • Specify which template folders to include
    • Specify file destination for each template folder to include, hence supporting component based development
  • Simple code. Less than 20 classes makes up the framework. 5 services and one repository does most of the job.

Check out SitecoreORM here:


Posted in c#, Sitecore, Sitecore 7 | Tagged , , , | 19 Comments

Sitecore.Data.ID The call is ambiguous

In Sitecore you cannot compare an ID with NULL; it will produce the following error:

The call is ambiguous between the following methods or properties: ‘Sitecore.Data.ID.operator ==(Sitecore.Data.ID, Sitecore.Data.ID)’ and ‘Sitecore.Data.ID.operator ==(Sitecore.Data.ID, Sitecore.Data.ShortID)’

I.e. the following code is invalid:

Sitecore.Data.ID someID = GetSomeID();
if (someID == null)
  // do code

Instead, you need to call Sitecore.Data.ID.IsNullOrEmpty():

ID someID = GetSomeID();
if (Sitecore.Data.ID.IsNullOrEmpty(someID))
  // do code

A quick tip for you.

Posted in c#, Sitecore, Sitecore 7 | Tagged , | 2 Comments

Get Sitecore placeholders and rendering hierarchy from a Sitecore item

This article explains how you can get the hierarchy of placeholders and render them to your screen for debugging or documentation purposes.

The Sitecore rendering engine allows you to place sublayouts inside placeholders. These sublayouts can contain more placeholders, thus creating a hierarchy of placeholders inside a page.
This hierarchy can get pretty complex. So the following code demonstrates how you can read the layout from an item, the placeholders from a layout or sublayout, which renderings will be rendered where and how to write it all to an XML document that will show you which sublayout contains which placeholders and which renderings is rendered where.


First i give you the basic methods for getting layout, placeholder and rendering information. These methods can be copied into your own project directly:

  /// <summary>
  /// Return all placeholder keys defined on one item
  /// </summary>
  private IEnumerable<string> GetPlaceholderKeys(Sitecore.Data.Items.Item item)
    List<string> uniquePlaceholderKeys = new List<string>();
    Sitecore.Layouts.RenderingReference[] renderings = GetRenderingReferences(item, "default");
    foreach (var rendering in renderings)
      if (!uniquePlaceholderKeys.Contains(rendering.Placeholder))
    return uniquePlaceholderKeys;

  /// <summary>
  /// Search for all placeholder controls in a specific file and return all the placeholder keys
  /// </summary>
  /// <param name="relativePath"></param>
  /// <returns></returns>
  private IEnumerable<string> GetPlaceholderKeysFromFile(string relativePath)
    string text = System.IO.File.ReadAllText(HttpContext.Current.Server.MapPath(relativePath));
    string pattern = "<sc:Placeholder (.*?) />";
    MatchCollection matches = Regex.Matches(text, pattern, RegexOptions.IgnoreCase);
    foreach (Match match in matches)
      string keyPattern = @"Key=""(.*?)""";
      Match keyMatch = Regex.Match(match.Value, keyPattern, RegexOptions.IgnoreCase);
      yield return keyMatch.Value.Replace("Key=", "").Replace("key=", "").Replace("\"", "");

  /// <summary>
  /// Return all renderings to be rendered in a specific placeholder on the "default" device
  /// </summary>
  private IEnumerable<Sitecore.Data.Items.RenderingItem> GetRenderings(string placeholderKey, Sitecore.Data.Items.Item item)
    Sitecore.Layouts.RenderingReference[] renderings = GetRenderingReferences(item, "default");
    foreach (var rendering in renderings)
      if (rendering.Placeholder == placeholderKey)
        yield return rendering.RenderingItem;

  /// <summary>
  /// Return all renderings from an item defined on a device
  /// </summary>
  private Sitecore.Layouts.RenderingReference[] GetRenderingReferences(Sitecore.Data.Items.Item item, string deviceName)
    Sitecore.Data.Fields.LayoutField layoutField = item.Fields["__renderings"];
    Sitecore.Layouts.RenderingReference[] renderings = layoutField.GetReferences(GetDeviceItem(item.Database, deviceName));
    return renderings;

  /// <summary>
  /// Get the layout from an item defined on a device
  /// </summary>
  private Sitecore.Data.Items.LayoutItem GetLayout(Sitecore.Data.Items.Item item, string deviceName)
    Sitecore.Data.Fields.LayoutField layoutField = item.Fields["__renderings"];
    return new Sitecore.Data.Items.LayoutItem(item.Database.GetItem(layoutField.GetLayoutID(GetDeviceItem(item.Database, deviceName))));

  /// <summary>
  /// Convert a Sitecore item to a Sublayout item
  /// </summary>
  private Sitecore.Data.Items.SublayoutItem GetSublayout(Sitecore.Data.Items.Item item)
    return new Sitecore.Data.Items.SublayoutItem(item);

  /// <summary>
  /// Get the device item from a device name
  /// </summary>
  private Sitecore.Data.Items.DeviceItem GetDeviceItem(Sitecore.Data.Database db, string deviceName)
    return db.Resources.Devices.GetAll().Where(d => d.Name.ToLower() == deviceName.ToLower()).First();

  /// <summary>
  /// Get all placeholder settings that defines the specified placeholderKey
  /// </summary>
  private IEnumerable<Sitecore.Data.Items.Item> GetPlaceholderSettings(Sitecore.Data.Database db, string placeholderKey)
    Sitecore.Data.Items.Item root = db.GetItem("/sitecore/layout/Placeholder Settings");
    foreach (Sitecore.Data.Items.Item descendant in root.Axes.GetDescendants())
      if (descendant.Template.Key != "placeholder")
      if (descendant["Placeholder Key"].ToLowerInvariant() == placeholderKey.ToLowerInvariant())
        yield return descendant;

Each of these methods can be used individually, but will reference each other some times.

To get all placeholders (i.e. the placeholder “keys” which is the unique definition of a placeholder) that contain renderings, call GetPlaceHolderKeys().

To get all placeholders that is defined in a file, call GetPlaceholderKeysFromFile(). This method uses a Regular Expression to extract all the <sc:Placeholder /> definitions found inside a source file.

To get all renderings that is rendered to a specific placeholder, call GetRenderings().


Here is how to use the methods. These 2 functions will render an XML structure of the hierarchy of layouts, sublayouts, placeholder etc. You should replace /sitecore/templates/somepage/__Standard Values with the page you wish to get the hierarchy from:

  void Page_Load(object sender, System.EventArgs e)
    Sitecore.Data.Database db = Sitecore.Configuration.Factory.GetDatabase("master");
    Sitecore.Data.Items.Item item = db.GetItem("/sitecore/templates/somepage/__Standard Values");

    Response.Write(string.Format(@"<template name=""{0}"">", GetLayout(item, "default").Name));
    foreach (string s in GetPlaceholderKeysFromFile(GetLayout(item, "default").FilePath))
      RenderPlaceholders(s, item);

  private void RenderPlaceholders(string placeholderKey, Sitecore.Data.Items.Item item)
    IEnumerable<Sitecore.Data.Items.Item> placeholderSettings = GetPlaceholderSettings(item.Database, placeholderKey);
    int settingsCount = placeholderSettings.Count();
    bool editable = placeholderSettings.Any(i => i["Editable"] == "1");
    Response.Write(string.Format(@"<placeholder key=""{0}"" editable=""{1}"">", placeholderKey, settingsCount, editable));

    foreach (var rendering in GetRenderings(placeholderKey, item))
      Response.Write(string.Format(@"<sublayout name=""{0}"">", rendering.Name));
      foreach (string s in GetPlaceholderKeysFromFile(GetSublayout(rendering.InnerItem).FilePath))
        RenderPlaceholders(s, item);

The method will output something like this:

<template name="Default">
  <placeholder key="SeoRegion" editable="0">
    <sublayout name="MetaTags"></sublayout>
    <sublayout name="DocumentDescription"></sublayout>
    <sublayout name="OpenGraph"></sublayout>
  <placeholder key="phPageHolder" editable="1">
    <sublayout name="DefaultPage">
      <placeholder key="DefaultColumn1" editable="0">
        <sublayout name="DefaultPage">
  <placeholder key="ScriptsRegion" editable="0">
    <sublayout name="GoogleAnalytics"></sublayout>

That’s it. Happy coding.

Posted in c#, General .NET, Sitecore 5, Sitecore 6, Sitecore 7 | Tagged , , , , , | 6 Comments

Register local search terms in Sitecore DMS

When installing Sitecore and DMS, Sitecore comes pre-installed with an Executive Insight Dashboard Report that will generate a report containing which search words users have executed in your local search page.

All you need to do is to register a Page Event called “Search” on your search result page:

using Sitecore.Analytics;
using Sitecore.Analytics.Data;

protected void RegisterSearchPageEvent(string searchQuery)
  if (!Tracker.IsActive || Tracker.Visitor == null || Tracker.Visitor.CurrentVisit == null)

  var page = Tracker.Visitor.CurrentVisit.CurrentPage;
  if (Tracker.Visitor.CurrentVisit.PreviousPage != null)
    page = Tracker.Visitor.CurrentVisit.PreviousPage;

  page.Register(new PageEventData("Search")
    Data = searchQuery,
    DataKey = searchQuery.ToLowerInvariant(),
    Text = searchQuery

What happens behind the scenes is that the search terms (the parameter “searchQuery” is registered as a page event on the current page. The page event “Search” is defined in Sitecore:

Page Event "Search"

Page Event “Search”

And a SQL Query Report is defined to get the visits per data query.

SQL Query

SQL Query

And the Executive Dashboard is configured to display the search terms from this SQL Query (you will find the report under “Site Search“):

Dashboard displaying the search terms

Dashboard displaying the search terms

Please note that the report will not display any data below 50 hits, unless you configure this in the .config file located here:


Look for the setting called “MinimumVisitsFilter“. This filter determines how many (or how few) visits are required before they are considered a significance.

In the demo above, I have set the value to “5”:

  <MinimumVisitsFilter value="5" />

Also note that this setting influences every report in the Executive Dashboard, so be careful not to set it too low or it will slow down other reports significantly.




Posted in .net, c#, Sitecore 6, Sitecore 7 | Tagged , , , , | 1 Comment

JavaScript ReferenceError: Can’t find variable: __doPostBack

This error can occur in asp.net pages. In certain situations .net will fail to create the __doPostBack JavaScript function and the hidden __EVENTVALIDATION input field. The situations that can cause this are:

  • When using asp:ImageButton or asp:LinkButton controls AND:
  • When viewing the webpage using IE11
  • When viewing the webpage using an iPhone or an iPad that was updated to the latest iOS 7.

The problem revolves around the BrowserDefinitions in .NET. .NET uses these Browser Definitions to identify the capabilities of the current browser. As per default, if a browser is not known (i.e. not defined in the BrowserDefinitions), .net assumes that the browser have no JavaScript capabilities, and therefore the __doPostBack function is not needed.

Assuming that a browser is not JavaScript compatible by default in the year 2013 is probably pretty stupid. However, this is the reality and we need to cope with it. 

The browserdefintions are defined in the belly of .net (for example here: c:\Windows\Microsoft.NET\Framework64\v4.0.30319\Config\Browsers).

The later a .net version you have, the newer the .net version, the more likely it is that the browser is known. .NET 4.5 should know about  IE11 and the latest iPhone and iPad browsers.


There is a way to override the automatic detection of browser capabilities. Add the following to the <% Page %> directive on all of your .aspx pages:

<%@ Page Language="C#"
    Inherits="somecode" %>

Setting ClientTarget=”uplevel” forces the page to generate JavaScript as it assumes that the browser has at least the capabilities of IE6.


Posted in .net, c#, General .NET | Tagged , , , , | 1 Comment

Sitecore ECM 2.1: The target device layout does not include ‘Processes Personalization Tokens’ sublayout og ‘Target item’ rendering

When using Sitecore Email Campaign Manager, you might encounter the following error:

The target device layout does not include ‘Process Personalization Tokens’ sublayout and ‘Target Item’ rendering, you may encounter this error for every variant in this message, if you have admin right to fix variant ‘A’, please click here to start the Layout dialog.

ECM Error

ECM Error

The error does not only occur if the rendering and the sublayout is missing, but also if they are placed imporperly:

  • The “Target Item” render needs to be the first rendering.
  • The “Process Personalization Tokens” needs to be the last rendering.
Peoper placement of the 2 renderings

Peoper placement of the 2 renderings

To do this you must place the Process Persinalization Tokens sublayout in a non-editable placeholder. This placeholder must be placed at the bottom of the control stack, as described in the image above.

Furthermore, do not use __Standard Values. ECM cannot find the Target Item and Process Personalization Tokens controls if they are located in the __Standard Values of the message root item.

You must copy all the controls to the actual item and delete the controls from the layout field of the __Standard Values. If you have added controls to the item with the page editor you will need to merge the layouts from __Standard Values to the item. See this arcticle on how to merge layout details.


Posted in Sitecore 6, Sitecore 7 | Tagged , , , , | Leave a comment

Merge Sitecore layout details using XmlDeltas

One of the features that Sitecore introduced somewhere in the Sitecore 6.x range is “Layout Deltas“,  the possibility to merge an item’s layout details with the layout details on the item’s __Standard Values template.

It means that you can add sublayouts to the __Standard Values, and still modify the sublayouts on the actual item, without overwriting __Standard Values.

Because instead of copying all the layout details from the __Standard Values, Sitecore will only keep a difference list on the item, not the entire layout details. Sitecore then uses the XmlDeltas field type to merge the two.

If you look at the raw values in Sitecore, you will see that in the “Layout” field of your __Standard values, the contents look like this:

<r xmlns:xsd="http://www.w3.org/2001/XMLSchema" >
  <d id="{FE5D7FDF-89C0-4D99-9AA3-B5FBD009C9F3}" l="{45D794F6-9DBB-4DBE-9826-606456562FB4}">
    <r id="{153F8C66-033E-456A-9C5F-A98D587C7A7E}" ph="" uid="{DE3402CB-9E79-4539-8C54-1DA8FB8D3733}" />
    <r ds="" id="{69EB7A6D-ACEF-4D06-A923-804918AA245E}" par="" ph="NewsletterHeadSection" uid="{CECCDC8D-3AF8-448D-A527-F8471C139FE9}" />
    <r id="{424A40CD-CAF3-45D9-87BA-CBE88C895A64}" ph="" uid="{48640574-E4FB-433B-97B4-0B202D609CB2}" />
    <r ds="" id="{A5975387-6B3A-4A43-BDF5-2A422057E518}" par="" ph="NewsletterBody" uid="{56CA9222-D31E-400A-B697-B620CF431DFF}" />
    <r id="{E429A2F3-DCFC-416E-ACB1-6BB7DE70C846}" ph="" uid="{7DBE3A38-12AD-42B7-8115-F50121D38B84}" />
    <r ds="" id="{175839E3-AEF4-4830-B679-0F51B90B438E}" par="" ph="NewsletterFooter" uid="{DA53887E-B21F-4C8B-A7D7-C3770B79DDF3}" />

But the “Layout” field of the actual item look like this:

<r xmlns:p="p" xmlns:s="s" p:p="1">
  <d id="{FE5D7FDF-89C0-4D99-9AA3-B5FBD009C9F3}">
    <r uid="{7B831873-DE0D-46AA-AA38-9B5A72A3A1B7}" p:before="r[@uid='{7DBE3A38-12AD-42B7-8115-F50121D38B84}']" s:ds="{C57FBE62-5181-49B8-BF6A-E7CEE7BED209}" s:id="{7CCB9656-AE33-4609-92F0-1FDC5632BB8B}" s:ph="newsletterbody" />

Notice the p:before attribue in the last XML? These are the attributes telling Sitecore how to apply the changes to the finished layout details.

You can do the merge yourself using the XmlDeltas field. This example merges the __Standard values onto the item itself:

using Sitecore.Data;
using Sitecore.Data.Fields;
using Sitecore.Data.Items;

/// <summary>
/// Merge layouts
/// </summary>
/// <param name="destinationItem">Item that receives the merged layouts</param>
/// <param name="standardItem">Item to merge from (the Standard Values usually)</param>
private string MergeLayouts(Item destinationItem, Item standardItem)
  LayoutField layoutDestinationItem = destinationItem.Fields[Sitecore.FieldIDs.LayoutField];
  LayoutField layoutStandardItem = standardItem.Fields[Sitecore.FieldIDs.LayoutField];
  string deltaLayout = XmlDeltas.ApplyDelta(layoutDestinationItem.Value, layoutStandardItem.Value);
    destinationItem.Fields[Sitecore.FieldIDs.LayoutField].Value = deltaLayout;
    return deltaLayout;
  catch (Exception ex)
    throw new Exception("Updating '" + destinationItem.Paths.FullPath + "' failed: " + ex.ToString());

It is the XmlDeltas.ApplyDelta that executes the merging.

Please notice that if you merge from __Standard Values, and later modify the item that was merges, Sitecore will identify the merge, and “unmerge” your merged item. It does so using the XmlDeltas.GetDelta() method:

string deltaLayout = XmlDeltas.GetDelta(layoutDestinationItem.Value, layoutStandardItem.Value);


Posted in .net, c#, Sitecore 6, Sitecore 7 | Tagged , , , | 2 Comments

Avoid the use of Sitecore.Context.Item

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" 
    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.

Personalize the Component

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" 
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.

Posted in c#, General .NET, Sitecore 6, Sitecore 7 | Tagged , , , , , , | 8 Comments