Querying generated Template Models with Glass

I have written some helper methods for working with generated Template Models and Glass.Mapper. Main goal is to make it easy for developers to query the Sitecore database using generated Template models.

See Mike’s post for details on what Template Models are.

Examples

Let’s start with this fictional content tree:

- Home (template: Home Page --> has Page as base template)
-- Page 1 (template: Page)
-- Page 2 (template: Page)
---- Sub Page 1 (template: Page)
---- Sub Page 2 (template: Page)
---- Data (template: Data folder)
-- News Page (template: News Page --> has Page as base template)
---- News Entry 1 (template: News Detail Page --> hase News Page as base)
---- Data (template: Data folder)
-- Page 3 (template: Page)
-- Search Page (template: Search Page --> has Page as base template)
-- Data (template: Data folder)

Now, let us get the home node using glass:

var homeItem = new SitecoreContext()
    .GetItem<IHomePageTemplate>("/sitecore/content/Home");

The IHomePageTemplate interface has been generated using TDS or any other tool of choice. It implements the IGlassBase interface.

Now, let’s get all the sub pages:

var subItems = homeItem.Children<IPageTemplate>();  
// Returns: Page 1, Page 2, News Page, 
// Page 3, Search Page (all templates that inherit from PageTemplate)

Now, let’s only get the news page(s):

var subItems = homeItem.Children<INewsPageTemplate>(); 
// Returns: News Page (as enumerable)

Now, let’s get only the search page:

var theSearchPage = homeItem.FirstChild<ISearchPageTemplate>(); 
// Returns: Search Page (as model implementing ISearchPageTemplate)

Let’s get all pages needed to build a page navigation:

var subItems = homeItem.Descendants<IPageTemplate>(); 
// Returns: Page 1, Page 2, Sub Page 1, 
// Sub Page 2, News Page, News Entry 1, Page 3, Search Page

Because IEnumerable is used, you can also go fancy with LinQ like this:

var subItems = homeItem.Descendants<IPageTemplate>()
    .Where(p => !p.HideFromNavigation); 
// Returns all items which inherit from Page 
// and don't have the HideFromNavigation field set. 
// (Assuming your Page Template has a HideFromNavigation checkbox field)

Build a breadcrumb:

var items = new SitecoreContext()
                .GetCurrentItem<IPageTemplate>()
                .Ancestors<IPageTemplate>()
                .Where(p => !p.HideFromBreadcrumb);

// (Assuming your Page Template has a HideFromBreadcrumb checkbox field)

If you don’t like to use extension methods, you can also use the helpers in a more DI-friendly way:

ITemplateModelHelper<IGlassBase> helper = new GlassTemplateModelHelper(new SitecoreContext());

var children = helper.Children<ISomeTemplate>(myItem);

Details

The helpers use a custom attribute called TemplateModelHelper. It needs to be included in code generation templates to let the helpers know which interface maps to which templateID and also to handle template inheritance. See the documentation on GitHub for details how to set up.

Example of a generated interface:

[SitecoreType(TemplateId=IMyTemplate.TemplateIdString)] // , Cachable = true
[TemplateModelHelper(TemplateId="076616fe-123f-443d-b627-ff4c1da8df57",BaseTemplates="453e35fc-46c5-46b3-a447-141c103f9989,0b34a6eb-d5b6-4d59-b5f9-3ce0bcb13fdd")]
public partial interface IMyTemplate : IGlassBase, IMyBaseTemplate, IMyOtherBaseTemplate
{
}

Performance

The helper methods introduce as little overhead as possible and have been tested for performance. By making sure, only the relevant items (=matching TemplateId) are mapped to template models, the helpers are very efficient.
The mapping Interface => TemplateID => Child Templates is done once and stored in memory as long as the application lives.

Get the code

If you like this way of querying Sitecore Items, feel free to grab the code from GitHub. Any feedback and improvements are most welcome.


Leave a Reply

Your email address will not be published. Required fields are marked *