There are three cornerstones to a content management platform – extensibility, storage, and display. The first milestone of Orchard revolved around the first two and the next push is taking a look at the third.
It takes a large leap of faith to retrofit the rendering system of an application. If the retrofit is based on significantly different concepts you don’t really have a choice but to enter a period of almost total loss of functionality. So here we are – jumping the canyon – looking forward to getting all of the modules back online over a new display system.
There are a lot of things we want to accomplish with what’s being designed. Trying to capture as many of the simple qualities you’d want from a direct template based approach along with the flexibility, power, and control you’ll need in a system like Orchard.
To that end we’re taking a lot of proven concepts and patterns, and bringing them all together as cleanly and transparently as possible with the tools we have at our disposal. Much of this will be leaning heavily on the IoC capabilities under Orchard’s extensibility story, and the dynamic capabilities provided by the upgrade to the latest dotnet fwk.
At the heart of the beast are some very old patterns. The most significant one is the Two Step View which: Turns domain data into HTML in two steps: first by forming some kind of logical page, then rendering the logical page into HTML. Looking at this one way you could think of this as a form of ViewModel. Looking at it another you could say this is a WebControl style approach. The goal is to be something in-between that’s not really one or the other.
This approach has very large implications in the way Orchard controllers and views relate to each other. There is a degree of overhead to using strongly typed view models – I like them myself but they are an additional class to create. An even larger problem – they are only meaningful to code that has a strongly typed compile time knowledge of their existence. Know what I mean? If you’re a module that wants to monitor or alter material as it’s displayed there’s not much you can do without getting heavily into reflection, and even then you’re not really free to alter the page results beyond manipulating the data within the bounds of the declared viewmodel structures.
For those reasons we explored and are delving into the use of dynamic object behaviors layered on top of normal clr types as the basis of a “Shape” page object model. The idea of a shape is to be a representation of the domain model that’s halfway into the page display vernacular – it shows a hierarchy that reflects logically what will be rendered, carries forward the information from the domain model in a way that’s still connected to it’s source, and may carry forward some rendering-specific information (like css classes and additional html attributes) but stops short of determining or being connected to the specific html that will be produced.
That last point is key – and it is the quality that stops the page object model from being compared to a web control rendering approach. Each web control knows how to render itself, that’s its job, but in this case the task of converting the shapes into html is a seperate concern. Essentially implementing a Strategy and Adapter pattern, there is a display manager available via @Display(anyShape) which will use the appropriate template or method to render the given shape.
It’s really nice, too, the fact that it can be any template or method. So if you have a Message shape, for example, the realization of shapes of type “Message” could be bound against either a view template like Message.cshtml or a public method on an IoC component with the [Shape] attribute. You can override or augment the description of a shape’s binding in modules or in your theme as well – the [Shape] method for the default Message rendering method in a module can be overridden with a Message.cshtml template in the active theme.
Of course this doesn’t mean a page object model will be returned from all controller actions in Orchard – it would be counterproductive to go to that extreme. But it’s a great way of representing information that is meant to be explored and manipulated by code from other modules. Forms that are expected to be extensible, for example, or the contents of page zones like sidebars. Where to use it, and what set of core shapes and their granularity, is all part of the art of software design in comparing alternatives.