Sitecore find Unused Sublayouts

Long lived Sitecore solutions tend to build up unused renderings and sublayouts as design, features and functions evolve. Finding those unused sublayouts it not just a matter of checking the Sitecore Link Database for sublayouts with no references because:

The problem seems easy at first: 1) Find all sublayots. 2) Find all pages using sublayots. 3) Those sublayouts not used on any pages are unused. And that’s what this code will check.

STEP 1: FIND ALL SUBLAYOUTS:

This repository returns every sublayout in your solution from a specified path:

using System.Collections.Generic;
using Sitecore.Data;
using Sitecore.Data.Items;

namespace MyCode
{
  public class SublayoutRepository
  {
    private readonly Database _database;
    private readonly List<SublayoutItem> _sublayouts = new List<SublayoutItem>();

    public SublayoutRepository(Database database)
    {
      _database = database;
    }

    public IEnumerable<SublayoutItem> Get(string rootPath)
    {
      _sublayouts.Clear();
      Item rootItem = _database.GetItem(rootPath);
      if (rootItem == null)
        return _sublayouts;
      Iterate(rootItem);
      return _sublayouts;
    }

    private void Iterate(Item item)
    {
      if (item.TemplateID == Sitecore.TemplateIDs.Sublayout)
        _sublayouts.Add(item);
      if (!item.HasChildren)
        return;
      foreach (Item child in item.Children)
      {
        Iterate(child);
      }
    }
  }
}

STEP 2: ITERATE ALL PAGES IN THE SOLUTION:

Finding used sublayouts are a little more tricky. Each item have a Visualization property and you need to iterate this to get the sublayouts from a specific device. In this example I have hard coded the device to “default“.

using System;
using System.Collections.Generic;
using System.Linq;
using PT.Project.Maintenance.Model.Repositories;
using Sitecore.Configuration;
using Sitecore.Data;
using Sitecore.Data.Items;

namespace MyCode
{
  public class FindUnusedSublayouts
  {
    private IEnumerable<SublayoutItem> _sublayouts;
    private List<SublayoutItem> _usedSublayouts = new List<SublayoutItem>();

    protected void Find()
    {
      _sublayouts = new SublayoutRepository(WebDatabase).Get("/sitecore/layout");
      _usedSublayouts.Clear();
      Item root = WebDatabase.GetItem("/sitecore/content");
      Iterate(root);
      var unusedSublayouts = _sublayouts.Where(s => !_usedSublayouts.Any(s2 => s2.ID == s.ID));
      foreach (var unusedSublayout in unusedSublayouts)
      {
        // Write the unused sublayout:
        // unusedSublayout.ID => The GUID
        // unusedSublayout.InnerItem.Paths.FullPath => The sublayout path
        // unusedSublayout.FilePath => The path to the .ascx file
      }
    }

    private void Iterate(Item root)
    {
      if (root.Visualization.Layout != null)
      { 
        foreach (var reference in root.Visualization.GetRenderings(DefaultDevice, false))
        {
          if (reference.RenderingItem != null)
          {
            try
            {
              SublayoutItem item = reference.RenderingItem.InnerItem;
              if (_usedSublayouts.All(s => s.ID != item.ID))
                _usedSublayouts.Add(reference.RenderingItem.InnerItem);
            }
            catch (Exception ex)
            {
              // Handle the exception, but do not 
              // stop the execution
            }
          }  
        }
      }
      if (!root.HasChildren)
        return;
      foreach (Item child in root.Children)
        Iterate(child);
    }

    private Database WebDatabase
    {
      get
      {
        return Factory.GetDatabase("web");
      }
    }

    private DeviceItem _device;

    private DeviceItem DefaultDevice
    {
      get
      {
        return _device ?? (_device = WebDatabase.Resources.Devices.GetAll().First(d => d.Name.ToLower() == "default"));
      }
    }

  }
}

MORE TO READ:

END NOTE:

I know that WebForms, .aspx and .ascx are dying technologies, and I encourage everyone to switch to Sitecore MVC. But a lot of older Sitecore solutions cannot switch to MVC for many reasons. Therefore it is important to help those who are maintaining large, long running Sitecore solutions.

About briancaos

Developer at Pentia A/S since 2003. Have developed Web Applications using Sitecore Since Sitecore 4.1.
This entry was posted in c#, General .NET, Sitecore 5, Sitecore 6, Sitecore 7, Sitecore 8, Sitecore 9. Bookmark the permalink.

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.