Friday 5 November 2010

An approach to Content Modelling with EPiServer CMS 6

Trying to avoid this!
How content is managed and presented are two different functions within content management systems. An obvious statement, well yes: however, complexity rears its head once you start to look at how each CMS or WCM or WCMS (take your pick) supports these activities.

Enterprise CMSs generally follow a strong separation between the content storage and management, and content presentation layers. For content storage there are open source technologies like Apache Jackrabbit and JCR which serve to store, provide an interface to and version content structures; including relational hierarchies.  For content management there are rich editor interfaces which leverage the storage mechanism capabilities. For content presentation, there are technologies which work well with the notion of hierarchical content model such as MVC frameworks.

However, with EPiServer CMS the distinction is not as clearly defined with its page tree and web forms implementation. The page tree works very well in scenarios where there is a tight coupling between pages and page data. In cases where there is a relational content model – a kind of domain model for content - this doesn’t really fit.

So how do you go about modelling a content tree with hierarchical, referential relationships in EPiServer CMS 6?
I found that there were no best practices and that there were a variety of techniques and technologies that could be used.

For example, there is the Dynamic Data Store (DDS) which seems to be an ominous shape lurking beneath the EPiServer framework. Try take it on with the wrong strategy and your CMS implementation could end up looking like the boat in Jaws I.

Another approach could be modelling the content hierarchy in a database and using EPiServer Page Providers to interact with the data. This, for me is over-engineered and doesn’t leverage the CMS platform.

After chewing over the options this I what consider a feasible approach. It takes advantage of Joel Abrahamsson's PageTypeBuilder and  PropertyPageTypeReference projects and Standard EPiServer Allowed PageTypes attributes.

Step 1: Model Your Content 

Using the modelling tool of your choice, create your content tree with entities and fields.
In this example I’ve modelled a basic structure with company and employee entities.


Step 2: Create Content Hierarchy

Create Page Types to model the Entities.
[ PageType(
    Name = "[Company] Company",
    Description = "This is a Company Data Entity",
    Filename = "~/Templates/ContentRepository/ContentRepository.aspx",
    AvailablePageTypes = new Type[] { typeof(EmployeeContainer) }
    )]
    public class Company : ContentRepositoryBase
    {
        [PageTypeProperty(Type = typeof(PropertyString))]
        public virtual string CompanyName { get; set; }

        [PageTypeProperty(Type = typeof(PropertyLongString))]
        public virtual string CompanyDescription { get; set; }
    }

    [PageType(
    Name = "[Entity] EmployeeNews",
    Description = "This is a EmployeeNews Data Entity",
    Filename = "~/Templates/ContentRepository/ContentRepository.aspx",
    AvailablePageTypes = new Type[] { }
    )]
    public class EmployeeNews : ContentRepositoryBase
    {
        [PageTypeProperty(Type = typeof(PropertyString))]
        public string Author { get; set; }

        [PageTypeProperty(Type = typeof(PropertyString))]
        public string Title { get; set; }

        [PageTypeProperty(Type = typeof(PropertyXhtmlString))]
        public string Body { get; set; }

        [PageTypeProperty(Type = typeof(PropertyDate))]
        public DateTime PublishedDate { get; set; }

        [PageTypeProperty(Type = typeof(PropertyDate))]
        public DateTime ModifiedDate { get; set; }

    }
Create EPiServer Page Types and associated Typed Page Reference Properties.
public class EmployeeType : ContentRepositoryBase, IEmployeeType
    {
        [PageTypeProperty(Type = typeof(PropertyString))]
        public virtual string Name { get; set; }

        [PageTypeProperty(Type = typeof(PropertyString))]
        public virtual string Description { get; set; }
    }

    [Serializable]
    [PageDefinitionTypePlugIn]
    public class PropertyEmployeeType : PropertyTypedPageReference
    {

    }
Create EPiServer Entity Page Types with Typed Page Reference Properties. In this example, Employee Type can only be set to PageType EmployeeType.
[PageType(
    Name = "[Entity] Employee",
    Description = "This is a Employee Data Entity",
    Filename = "~/Templates/ContentRepository/ContentRepository.aspx",
    AvailablePageTypes = new Type[] { typeof(EmployeeNewsContainer) }
    )]
    public class Employee : ContentRepositoryBase
    {
        [PageTypeProperty(Type = typeof(PropertyEmployeeType))]
        public virtual string EmployeeType { get; set; }

        [PageTypeProperty(Type = typeof(PropertyString))]
        public virtual string EmployeeFullName { get; set; }

        [PageTypeProperty(Type = typeof(PropertyLongString))]
        public virtual string EmployeeBiography { get; set; }
    }
Create Container Page Types with specified available page types to define the hierarchical relationship.
[PageType(
    Name = "[Container] Employee",
    Description = "This is a Container for Employee Entities",
    Filename = "~/Templates/ContentRepository/ContentRepository.aspx",
    AvailablePageTypes = new Type[] { typeof(Employee) }
    )]
    public class EmployeeContainer : ContentRepositoryBase
    {

    }

Step 3: Build the rest

Now that your Pages have been created and the hierarchical and referential relationship enforced; your EPiServer Page Tree should look something like this.


The next step would be to build Page Tree PageTypes which may include Standard Page Types, Page Types with references to Entities within the Content Repository or – if you are using Composer - Functions with Typed Page References to Entities within the Content Repository.

I’m sure this is probably a common implementation and that there are many similar approaches which with their own unique twist.

I’d be interested to hear about other EPiServer CMS Implementation styles; especially the ones which – through painful experience – have delivered some important learnings.

After all, after watching Jaws I now know never to take on a giant shark in a little fishing boat.

No comments:

Post a Comment