This post goes back to the basics. Find out the best way to determine if you have the right kind of item.
A very common task in Sitecore development is to test an item to see if it is based on a particular template. Ancestor fallback, iterating over a folder of items and filtering search results are just a few cases where you might want to do this. For as long as I can remember, I have been using a method like the following for that purpose.
I quietly congratulated myself on this long-overdue epiphany and threw down a bit of code something like this:
And then several of my unit tests promptly erupted into angry red flames.
I found that the failing tests were the ones that were testing items that did not have the field in question. For some reason, asking for a field that did not exist on the item was still returning a field. I knew that something must be wrong. Then I started to question my own sanity. Asking for a field by name returns null, so why not by ID?
It turns out that when you use the ID-based indexer for the Fields collection, it simply news up a field with that ID. It’s not until you start using the properties of that Field object that it tries to get the field from the template.
I started looking for other ways to test for the existence of a field and was rather disappointed by what I found. Using the string-based indexer for the Fields collection to get the field by name works, but I wanted to follow best practices and use field IDs. Using item.Fields.Contains(fieldId) doesn’t work properly unless you first call item.Fields.ReadAll(). I found that testing item.Fields[fieldId].Definition != null works correctly, but it seems kind of hacky. Using TemplateManager.IsFieldPartOfTemplate(fieldId, item) also works correctly and, while I’m not crazy about using a static method, it’s better than the other options.
I decided to do some performance testing to see how these options compare. I created a 3-deep template hierarchy, with a field on the first level. I used Rocks to create 100 items based on the third-level template. Then I tested each of the methods that I had found that actually worked correctly in a loop over those 100 items. For comparison, I also tested the IsDerived extension method above. I cleared all the caches before the first run, but not the second run. Here are the results:
As you can see the IsDerived method was by far the slowest, coming in at over twice the time of the fastest method. Reading all of the fields and then using Fields.Contains was somewhat better. The remaining three methods were pretty comparable, but TemplateManager.IsFieldPartOfTemplate seemed to come out slightly ahead most of the time. It’s certainly not a big enough difference to make me want to go back and change old code. But, moving forward, I’ll try to use my new extension method: