.NET, LINQ, Sitecore

Inheritance techniques in Sitecore ASP.NET CMS


There are two techniques for inheritance which are commonly used in all Sitecore solutions; hierarchical inheritance and template inheritance. Sadly, Sitecore offers no straight forward out-of-the-box API methods for the two techniques. This post describes some simple and neat ways of implementing these techniques – and also shows of how to use extension methods in .net to extend Sitecore and ASP.NET classes. This post was partly inspired by the extension method contest at the Learn Sitecore website.

Template inheritance:

Template inheritance is an integral part of Sitecore which I hope that all of you Sitecore fans out there use extensively in your solutions. At Pentia, template inheritance is so vital that in practice, you will see no item.TemplateID == SomeID or item.TemplateKey = "sometemplate" in any of our code, just like you (hopefully) would never use MyObject.GetType().Name == "MyClass" in C#.
No, we always use the following extension method:

public static bool IsDerived(this Item item, ID templateId)
{
  if (item == null || templateId.IsNull || item.Template == null)
    return false;
    
  TemplateItem templateItem = item.Database.Templates[templateId];
  if (templateItem == null)
    return false;

  Template template = TemplateManager.GetTemplate(item);       
  return template != null && (template.ID == templateItem.ID || template.DescendsFrom(templateItem.ID));
}

The method is used as item.IsDerived(“MyTemplate”) just as you would always do MyObject is MyClass in c#. Sadly, Sitecore offers no obvious way to do the same out-of-the-box….wait… oh yeah, you could naturally do Sitecore.Xml.Xsl.XslHelper.IsItemOfType()

Hierarchical inheritance:

While template inheritance is used to give all content of different types the same properties, hierarchical inheritance in Sitecore is slightly different. This is primarily used to allow a piece of content, a setting or a configuration to propagate down a branch in the tree – i.e. propogate down a number of content types which can be totally unrelated, but grouped together solely because of their content position. For example, this could be used to apply a given design theme to an entire subsite within you site. Using hierarchical inheritance, extension methods and Linq, this could be accomplished as such (pardon the train-wreck):

protected void Page_Load(object sender, EventArgs e) {
  var theme = this.GetDataSourceItem().GetAncestorOrSelf().First(i => i.IsDerived("HasTheme")).Fields["Theme"].Value;
  //...
}

In this example there are – besides the IsDerived extension method described above – two very useful extension methods:

GetDataSourceItem extends the ASP.NET UserControl to provide easy access to the DataSource set on a sublayout and is implemented as follows:

public static Item GetDataSourceItem(this UserControl control)
{
  Sublayout sublayout = GetSublayout(control);
  if (sublayout == null)
    return null;
  string dataSourcePath = sublayout.DataSource;
  return !String.IsNullOrEmpty(dataSourcePath) ? Context.Database.GetItem(dataSourcePath) : null;
}

GetAncestorOfSelf extends item to return a list with the item itself and all its parents – and this is naturally where the key to hierarchical inheritance lies:

public static IEnumerable<Item> GetAncestorOrSelf(this Item item)
{
  do {
    yield return item;
    item = item.Parent;
    
  } while (item != null);
}

I hope this post shows you how some simple extension methods can give you a lot of power in your solutions.

Standard

11 thoughts on “Inheritance techniques in Sitecore ASP.NET CMS

  1. Ivan Sharamok says:

    Great insight on inheritance techniques in Sitecore!

    One question on usage of template.DescendsFrom method. Why did you choose to use DescendsFrom instead of InheritsFrom? The last one seems to have better performance as it looks for a template matching in a direct base templates collection first and if it’s not there it starts looking further.

    • Eldblom says:

      Hi Ivan. You are probably right about performance – I have no preference for one above the other – actually our implementation at Pentia caches the result for each set of templates.
      One could argue though, that the problem lies in the fact that there are two methods in Sitecore which has the same apparent purpose but two different implementations. Wonder which one the Sitecore XslHelper class use, as this is most likely the most used since it is the most apparent?

      • Ivan Sharamok says:

        I looked into 6.5 Update-2 assembly and could not find IsDerived method for XslHelper class. Maybe it was in older versions…
        Anyways, if you cache the results changing your logic to use the other method would not give you a drastic change in performance.

      • Eldblom says:

        My bad – the method is called IsItemOfType and has been around for ages – unlike any ASP.NET version which shines with its absence. And by the way: IsItemOfType uses InheritsFrom (fixed in the post text)
        But if you choose to use InheritsFrom over DescendsFrom, please choose the ID version over the name one

  2. Very nice post, thanks.

    Just to be clear about this, you’re saying with your hierarchical example that you essentially traverse up the tree to all parents of an item until you find an item that derives the template with the field you’re looking for? Can you provide another example other than the theme example for Hierarchical inheritance?

    Thanks,
    Mark

    • Eldblom says:

      Hi Mark.
      Yes, your understanding is right.
      We always use hierarchical inheritance extensively in our solutions. Finding the submenu or subsite root is another example. Taxonomy is also more commonly derived hierarchically than through standard values – content in one branch is often about the same topic or have the same responsible editors.

  3. Alistair Deneys says:

    Hi Thomas,
    Nice post. Just another point of view on the template inheritence, with Sitecore we don’t need to get hung up on having an item which derives from a specific template. Instead, we can borrow an idea from the JavaScript world and “field detect” (feature detect in JavaScript). I don’t care if the item is derviced from “breadcrumb” template, all I care about is the item I’m dealing with has “breadcrumb title” and “include in breadcrumb” fields. If the item has those, then I can provess the item in my component, otherwise just return.
    One thing to note about template inheritence though is the semantic meaning you can place on items when using it. For example if the item does not inherit from my “breadcrumb” template above I don’t even evaluate whether the item can be included in the breadcrumb or not. This would make it simple to exclude folders from appearing in the breadcrumb rather than just checking if the “include in breadcrumb” field exists and is ticked. Another example would be the conceptual “site root” item (as you mentioend above in the comments).

    • Eldblom says:

      I agree that the semantic meaning of whether an item is a given template is a strong feature of Sitecore – perhaps one of the strongest when it comes to data security and consistency.
      Regarding the “field exists” method – or duck typing (“if it floats and quacks its a duck”) if you have it – or DecendsFrom or InheritsFrom, I see this merely as optimization (and perhaps the premature sort)

  4. Because we use generated wrapper classes, we can enforce template inheritance by using the C# way: myItem is MyTemplate. This also makes it very easy to see for what templates certain functionality is written, because you can have methods only accept objects of type MyTemplate as a parameter.

    • Eldblom says:

      We have a very similar approach to decorating the items.
      Have you actually overridden the is operator? We have generic extension methods (IsValidType() and CreateAs()) to transform items to classes.

      • We intentionally did not override the ‘is’ operator; I think it makes code less readable.

        We have similar methods to create/check wrapped versions of items. Once wrapped, the items have methods to follow relationships, and those methods return wrapped versions as well. So usually, we only have to wrap the first item we encounter.

        Here’s a link to the module we use: http://trac.sitecore.net/CompiledDomainModel

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s