Sitecore: Checking for existence of a field in an item

Check for existence
One of the most common tasks when developing for a system where the users of the system may alter the data model, is to check that the indata is always correct. Assume that if is possible to have different indata, then expect the power user to be able to provide a piece of unexpected data.

One of the really great things about Sitecore is they way to build content in a tree structure with folders grouping different types of content together to benefit from sorting and attributes on the objects below. A typical solution could be a blog post, that may consist of a structure of:

  • Blog post about LED Dimmers
    • Product References (folder)
      • Dimmer X 20-315W GLE
      • Dimmer Y 40-600W GLE
      • Dimmer Z 0-100W for LED
    • Related Blog Post References (folder)
      • What is the difference between a light bulb and a LED lighting source
      • How to use a dimmer for electronic transformators

In such a case, the objects are probably not inheriting from the same base templates as the blog post, and if it is also possible to have a structure for blog entries underneath the blog entry, you need to make sure that any logic that is processing the child items also is sure which content to expect.

You could of course check for which template ids that are applicable as child items, but this would not be a great solution, since a change in design may cause you having to re-deploy the code in order to add a new data template.

The solution is to use the Sitecore template structure to inherit base templates which will add functionality to the page and by doing this, we will make it possible to have the logic work and be future proof in a much better way. I’m for instance using the type of base templates as:

  • Page Metadata – this is a page that will contain the neccessary metadata to work as a stand-alone page with a title, meta description and other meta tags that may be needed for the project.
  • Page in Navigation Structure – the metadata for making the page part of the navigation structure.

When at first working with Sitecore, it felt odd that an attribute may only exist once in the template structure, and it was easy to thing that the Meta Description field could be created for each template. This is of course not a good way of doing it even if is possible, but that won’t give you the benefit of dynamic data model changes that you will have by inheriting page capabilities by inheriting base templates.

The really good thing about inheriting base templates for template names, is that you don’t have to refer to a field by it’s name, you can instead refer to it by it’s ID and a set of constants that the logic that requires the fields know their ID and access them like that instead of by the field name.

Define the attributes in a constants class:

public class ModelFields {
  public static ID MetaTitleID = new ID("{499946DB-175A-4A41-88C7-103F513A24D0}");
  public static ID MetaDescriptionID = new ID("{DB3B8336-DDCC-460A-B522-52E4966CBBD3}");
}

public class ModelTemplates {
  public static ID PageMetadataTemplateID = new ID("{F7AD3B12-F155-49EA-9B46-C6112722BDB4}");
}

Then, you could check if the current item’s template is a decendant of the base template that contains the required fields by introducing a method.

public static bool InheritsBaseTemplate(ID baseTemplateId, Item item)
{
    if( baseTemplateId.IsNull ) return false; 
    if( item == null ) return false;
    var itemTemplateDefinition = TemplateManager.GetTemplate(item);
    if( itemTemplateDefinition == null ) return false;
    return itemTemplateDefinition.DescendsFromOrEquals(baseTemplateId);
}

This nice little utility method gives me the ability to always check that a child item is applicable:

foreach (var child in item.Children)
{
   // Make sure this item inherits the Page Metadata Template 
   // to proceed to processing logic
   if ( ! ItemUtil.InheritsBaseTemplate(
            ModelTemplates.PageMetadataTemplateID, 
            child)) 
      continue;

   // Do logic when the selected template exists
}

There is also an alternative way of testing for just a specific field instead of the entire template, since each field is unique by it’s ID. We are always using the serialization tools to ensure that fields share the ID between environments, it’s always possible to refer to a field by it’s GUID and then there is no need to load the template to check wether the field exists.

foreach (var child in item.Children)
{
   // Make sure this item inherits the Page Metadata Template to 
   // proceed to processing logic
   if (!TemplateManager.IsFieldPartOfTemplate(
           ModelFields.MetaTitleID, 
           child)) 
       continue;
   
   // Do logic when the selected template exists
}

As of many things in Sitecore, it is for you to decide which method to use. I tend to use both methods.

Before reading this, you have probably already tested some of the not so reliable methods:

// Typical Null Reference Exception problem
if( item.Fields["Meta Title"] == null ) continue;

// Another Null Reference Exception problem
if( item.Fields["Meta Title"].Value == null ) continue;

The problem with both of the above examples is that the item is not fully loaded. In order to test for all the possible fields, you would have to load all the fields of the item

item.Fields.ReadAll();
The following two tabs change content below.

Fredrik Gustavsson

CEO, IT-consultant at Jolix AB
Software and integration magician with an interest in how to improve commerce in a multi channel environment. Owns his own IT-consultancy business and runs an e-commerce store that has a physical store. Will write blog posts on how to take his own store into the future.