I recently had a discussion with someone about how best to store collections in EPiServer, such as RSS feeds, advertisements, frequently asked questions, customer details etc. Here are my thoughts...
Using custom properties
If you wanted to display a collection of objects on a page, then usually you might create a custom property with a suitable interface so that editors can add to, and maintain the list. You could then register this property for a particular page type - so that each page of this page type can have its own list, or as a dynamic property - so that it is available as a shared list, and available across multiple page types.
This probably makes the most sense. However, the problem with this is that there is often a lot of development that needs to be done, e.g.:
- Developing a suitable editor for the collection (which might need to allow sorting, grouping, searching, validation etc.)
- Developing the web control that will render the list from the serialised data.
- Adding the more advanced features that your business might need, such as workflows for approvals, scheduling the inclusion and deletion of items from the list, security and so on.
Even if you are sure that you know exactly what your business requires, there is still the chance for scope creep, and a future of upgrades and maintenance.
Using pages
One of the ways to make your life easier is to create your collections as EPiServer pages. This instantly gives you a huge amount of the functionality you might require to manage the items. You will have the ability to:
- Easily define the properties of the items through their page type
- Add workflows such as approvals
- Set up access for different users and groups with different privileges
- Use the many EPiServer page list controls that are available to render the list
And your editors will be able to:
- Perform the usual C.R.U.D. operations
- Organise items in a list or hierarchy, with grouping and sorting.
- Search for items etc. etc.
In short, EPiServer is designed to manage a large collection, and this is what it does well! Of course, an item (in these sorts of collections) is a kind of content that does not directly correlate to a page on a website, so it might seem a bit foreign to re-use this functionality. However, it is a simple matter make sure that no-one can browse to an item (which now has its own URL) by adding some redirection or error trapping logic to the load event of the item’s page type ASPX, or through an event handler on the BeginRequest event. Actually it might be good to have the ability to display a page per item, if you wanted to give editors a preview how the item might look when displayed in a list! :)
There are some down sides though. EPiServer makes some assumptions about your items. It thinks they are pages of a site! This means adding a huge amount of overhead to them. The database stores a lot of information about pages in EPiServer that you might not want, and this, combined with the fact that the relational model isn’t going to be entirely optimised for your needs, will make data access slower than it needs to be. The API used to get page data back from the database is optimised in certain ways (such as retrieving the properties of the page), but this won’t do you any good if you have related objects in your list. You will often need several database reads on each page request. Caching may only get you so far as well.
Nowhere can potential performance issues been seen better, than in the page tree in the EPiServer edit mode. Imagine if you had thousands, or even millions of items in your collection. This interface is not designed to support lists of this scale. Even when in optimised mode, if your items do not lend themselves nicely to being stored in a hierarchy, and end up all under one parent node, then the interface will eventually become unusable, and you’ll need to write your own.
With a large collection of pages, you may also face performance issues on individual page requests, since the default EPiServer URL provider will have to search through all of your pages to find the page ID which corresponds to the requested URL.
If performance and scale are issues for you then the last resort is to start...
Using a custom data access layer
In the end, creating your own tables and stored procedures etc, may be the way to go, since you have so much extra control over the functionality, but generally I wouldn’t recommend it unless you really need to. EPiServer has so much functionality that can be re-used, it would seem silly to me not to try.
Summary
To summarize, using pages for your business objects is often a very good solution which is quick to implement and easily adopted by your editors. But what you need to bear in mind is that EPiServer is not a content management system in the literal sense. ‘Page management system’ would be more accurate, and if you’re thinking of using pages to manage your collections, you need to be sure that performance not be a problem.
It would be nice to see EPiServer change (or expand) their architecture in the future for enterprise applications in need of managing more than just pages. Of course, for specific markets, products and plugins are already available (EPiServer Community for instance).