EPiServer  /  CMS December 13, 2009

Get child pages filtered by page type

When using Page Type Builder we can easily filter collections of pages based on type by using LINQ.

I received an e-mail today asking how you can get all children of a EPiServer CMS page that are of a specific page type when you use Page Type Builder. Since this is a very common scenario I thought I’d post my reply here.

When you call DataFactory.Instance.GetChildren() with a page’s PageReference as a parameter the method will return a PageDataCollection with all children of the page. Normally all of the PageData objects in the returned collection are of type PageData. However, when you use Page Type Builder their underlying type is actually a subtype of PageData. That is, if you know that all of the returned children are of type ArticlePage you can do this:

IEnumerable<ArticlePage> children = DataFactory.Instance.GetChildren(pageLink).Cast<ArticlePage>();

If on the other hand you aren’t sure that all children is of the type you can filter out those who aren’t by using the Where LINQ extension method.

IEnumerable<ArticlePage> children = 
    .Where(child => child.GetType() == typeof(ArticlePage))

The above code will produce a set of pages whose page types are exactly ArticlePage. Often though you would also want to include pages whose page type are either ArticlePage or a descendant of ArticlePage. That’s accomplished by the below code, which also looks more elegant thanks to the is operator.

IEnumerable<ArticlePage> children = 
    .Where(child => child is ArticlePage)

An extension method for getting child pages filtered by type

If we use this type of filtering often we could create a nice little extension method for DataFactory that does it for us.

using System.Collections.Generic;
using System.Linq;
using EPiServer;
using EPiServer.Core;
using PageTypeBuilder;

public static class DataFactoryExtensions
    public static IEnumerable<T> GetChildrenOfType<T>(
        this DataFactory dataFactory, PageReference pageLink) 
        where T : TypedPageData
        return dataFactory.GetChildren(pageLink)
            .Where(child => child is T)

Using FindPagesWithCriteria

The above solution does all filtering in memory. That’s usually fine performance wise, but there are situations where a page has thousands of children and it’s better to do the filtering in the database. In that case we can use the PageTypeResolver class to figure out a page type’s ID and then use FindPagesWithCriteria. The code below will produce the same result as the second code example except that it will include all descendants and not just children (add a critieria for PageParentLink if you just want children).

//Figure out the corresponding ID for the 
//page type that matches the ArticlePage type
int pageTypeID = PageTypeResolver.Instance.GetPageTypeID(typeof(ArticlePage)).Value;

PropertyCriteria pageTypeCriteria =  new PropertyCriteria();
pageTypeCriteria.Condition = EPiServer.Filters.CompareCondition.Equal; 
pageTypeCriteria.Name = "PageTypeID";
pageTypeCriteria.Type = PropertyDataType.PageType;
pageTypeCriteria.Value = pageTypeID.ToString();
PropertyCriteriaCollection criterias = new PropertyCriteriaCollection();

IEnumerable<ArticlePage> descendants = 
    DataFactory.Instance.FindPagesWithCriteria(pageLink, criterias)

PS. For updates about new posts, sites I find useful and the occasional rant you can follow me on Twitter. You are also most welcome to subscribe to the RSS-feed.

Joel Abrahamsson

Joel Abrahamsson

I'm a passionate web developer and systems architect living in Stockholm, Sweden. I work as CTO for a large media site and enjoy developing with all technologies, especially .NET, Node.js, and ElasticSearch. Read more


comments powered by Disqus

My book

Want a structured way to learn EPiServer 7 development? Check out my book on Leanpub!

More about EPiServer CMS