Customized Transformation of IContent for ContentDeliveryApi
I've created a convenient pattern to more easily customize and add additional data to the ContentApiModels delivered by ContentDeliveryApi. There are apparently some questions flying around about how to best use it, and I'll be glad to post my idea on one way to do it.
Why customize it?
The ContentDeliveryApi does much of the magic in the background (which is good), but it's not entirely obvious how to extend it in certain ways. Episerver's own Music Festival SPA demo gives a clue on how to do it with the ExtendedContentModelMapper which intercepts the transformation, but that demo only adds an URL and flattens the properties for all pages.
I've often needed to add some data that should be for all pages, and some which should be specific to some pagetypes. Essentially like a controller for ContentApi. PropertyConverters does this for properties on pages, but there was no obvious way to do the same for pages and blocks.
What does it do?
The pattern, for lack of a better word, extends the ExtendedContentModelMapper from Music Festival with the ability to add custom model converters for all types of IContent, i.e. pagetypes, mediadata, and blocks - the exception being for blocks as properties, which are handled by propertyconverters.
- During startup it scans the assembly for any classes implementing a specific interface.
- When a page is requested through ContentDeliveryApi it enters the ExtendedContentModelMapper, which finds the correct converter for that IContent.
- The converter uses the default IContentModelMapper for initial transformation, which makes this pattern essentially maintenance-free, then you can add any additional data to the ContentApiModel.
- Afterwards the resulting ContentApiModel is sent to the client as usual.
It supports an optional hierarchy so that e.g. a BasePageConverter can provide language links which all pages should have, then the specific pagetype can add additional data like user-specific information.
Being able to have all this in one spot makes it easier to handle, works essentially like a controller so that devs can follow-ish the MVC-pattern, and alleviates the need for extra web API-calls for page-specific information. Since it finds the converters through assembly scanning there's no need to register them anywhere.
Update! Dependency injection is now supported
I have now added dependency injection to the converter-classes. It uses StructureMap as the IoC tool. The code is on the master branch.
If you prefer to not have dependency injection, or plan to use another tool, the basic code is in the branch "Basic_without_dependency_injection".