Working with View Models in Umbraco and EPiServer
Zone’s head of .NET development, Andy Butland, wants to share some thoughts on the utilisation of view models within the Umbraco and EPiServer CMSs…
When working on web applications on the .Net platform at Zone we find they usually fall into two categories. The first would be what I would term perhaps “vanilla” web applications, mostly using the ASP.Net MVC framework directly. Others are built upon a content management framework, generally Umbraco or EPiServer.
With the former we’ve been influenced by a number of best practices for building MVC applications — including dependency injection, programming to interfaces, separation between domain and view models and unit testing. And when working within the context of a CMS we look to apply them too.
In this article I’m planning to illustrate options for utilising view models with the CMS platforms Umbraco and EPiServer. Both products have a well-developed MVC implementation allowing you to use this style for rendering your content. In order to take full control of the page rendering process, the approach is to create a controller using a particular convention that will lead to a defined action method responding to a request for a page of a particular type. Within that method you have access to the details of the page that’s being requested and — if you are so inclined — you can construct your own view models, populate them and pass them to a view.
For neither platform is it necessary to follow this approach and whether it’s a preferred way to go in any given situation will depend on a number of things, such as scale of the application being built and the background and preferences of the developers working on it.
Domain and view model separation
A key concept to define first is that of the domain model and the view model. These terms and the differences between them are fairly well established within the context of MVC style applications. The idea being that the domain model is part of your application core — it will contain a set of related entities containing properties and perhaps some behaviour in the form of methods. It will usually have quite a close relationship with however the data for your application is stored, which, if a SQL database is used, usually maps closely to the table schema.
A view model by contrast is constructed to service the presentation layer. It will be a representation of the data required to render a specific view. In some cases, it may be very similar to a given domain model class, but in practice a precise one-to-one relationship is quite rare. Normally the view model will contain perhaps a sub-set of the properties of a given domain model, and/or contain properties from a number of related domain models or even other sources as well. The properties may also be flattened from a more complex object graph and some concatenation, formatting or other modifications to the property values may be applied.
Given that, it’s considered best practice to not pass instances of domain models direct to a view. Instead a view model is constructed and populated, often with the help of a mapping tool, and that is what is passed as the model for the view.
There’s a little more effort in doing that of course, but the result is a very clean view containing only the necessary, easily accessible properties for rendering the page. Particularly when there’s a number of developers working on a project, perhaps in a front-end/back-end split, that can be very valuable.
Application to CMS projects
A question then arises when working on CMS projects around what we consider our “domain model”. It’s the CMS data itself, namely the definitions of pages based on document or content types and the representations of the instances of content created using those types.
In Umbraco this would be the instances of IPublishedContent that we work with in the templates or controllers. For EPiServer it’s the strongly typed classes that inherit from PageData.
In both platforms it’s quite possible to access that data directly in the templates or views, as well as to query for other information from the CMS from this location. Doing so is rather going against the separation I’ve discussed above though. In fact both platforms will support the construction of a custom view model which can be passed to the view and it is how we can do this with the two CMS products we use that I’m going to get into further in this article.
Strongly typed view models with Umbraco
With Umbraco, in addition to the advantages of using view models discussed above, by creating and populating these we can also get the benefits of strong typing in our views — Intellisense and compile time checks for any typos. The reason for this is that accessing page properties in Umbraco from the IPublishedContent instances is itself not strongly typed — rather I’ve seen it referred to as stringly” typed.
In short to access a property we need to do something like this (or use dynamics, but these have the same issues with lack of compile time checking).
Rather than what we might ideally prefer:
Working with strongly typed view models with Umbraco is something we’ve been doing for a while and that I’ve spoken and blogged about before. A number of other people have too and so currently there are a few solutions to the problem, that break down into two approaches.
The first is to take the instances of IPublishedContent and map them to custom view model classes. This can be done manually of course in code, but a mapping package or routine can remove a lot of this need to write potentially error-prone “left-right mapping” code. These will use reflection and conventions to map IPublishedContent property values to fields on the view model. The earliest published example of this method I’ve seen is an article by Darren Ferguson on “24 days in Umbraco” from 2013, which still succinctly describes the essence of the approach very well. We make use of the Umbraco Mapper package for working in this way; another well recommended and established solution is Ditto.
The second approach would be to first focus on converting the Umbraco content representations into true strongly typed models. For this the most widely used approach is likely the Zbu Models Builder. This works by analysing the document type structure and generating C# class files that represent them, by wrapping the calls to GetPropertyValue(). These strongly typed models can then be used in our controllers or views as is preferred, giving us the compile time checking and Intellisense benefits.
We can then take the additional step of mapping these models to view models, to go the full way of separating out the “domain” model from the presentation layer view models. For mapping, it’s likely the well-established AutoMapper library is the best approach to use here, as we are now simply mapping between .Net classes and can use tools developed outside of the Umbraco ecosystem.
Strongly typed view models with EPiServer
Moving onto consider EPiServer, the first thing to note is that we are already further along the path to strongly typed view models than we are with Umbraco, in that EPiServer adopts a code first method for content type creation. There have been a few attempts to do this with Umbraco but none that have really established, or are necessarily welcomed as an approach, whereas with EPiServer this comes out of the box.
What it does mean though is that we already have in place a strongly typed representation of our content, so really for EPiServer we only need to consider if we’ll get sufficient benefit out of constructing and using dedicated view models for our a views.
I suspect most people considering this issue with EPiServer fairly soon end up on this article by Joel Abrahamsson where he considers how the view model practice stacks up in the CMS world and outlines the approach that has been used in the EPiServer distributed sample website AlloyTech.
It’s an approach most EPiServer developers are likely familiar with and one we’ve mostly followed to use on the recent projects we’ve built with the platform. For pages that really are representations of a single content type, defining our model for the view as with model IPageViewModel<MyPageType> and accessing the strongly typed page properties via Html.PropertyFor(p => p.CurrentPage.MyProperty) leads to a very clean view.
Where we have more complex pages, that require data from content stored outside of the current page being viewed, or from other sources such as a custom database, we inherit from a base view model and add and populate additional properties as required. Again, this leads to the simple access of strongly typed properties we would like to see in the view.
That said, there’s a still an improvement here we can consider, as when viewed from the bottom-up perspective of the view, it’s clear we are making some small concessions to the framework when defining our view models. It would arguably be better if we could remove the `CurrentPage` property and access the properties in a more flattened structure from the view.
For example taking an illustrative view model such as this:
It’s not immediately obvious from a view/view model perspective, where ideally we want to be ignorant of where each field of content comes from, that we have to access some properties like this: Model.CurrentPage.MyProperty and others like this: Model.MyCustomString.
So, could we adopt a similar approach to that used in standard MVC applications and map from the instances of our page types to a pure POCO view model? There’s no reason why not, as we are working with standard .Net classes we could again use a library like AutoMapper to help with the population of a simple view model such as the following, and pass that to the view as its model.
There is one downside to this approach with EPiServer that comes from that fact that the product supports a feature editors often find useful, which is that as well as the “form based” view for editing they can also work with a WYSIWYG style editor to make changes in-place on a page. With the above in place though, this would break down. There’s nothing in the view model to indicate that MyProperty is a field on the current page and hence should be available for editing in-place in this way.
To manage this though, there’s a feature available called editing hints, which is a way of configuring connections between properties on the view model and their related properties on the content data object.
The simplest way to do this is firstly to ensure that the Html.PropertyFor helper is used for rendering the property (rather than simply using Model.MyProperty). If this is done, and the property on the view model has the same name as one on the page type, the connection will automatically be made and the field will be available for editing.
Where the names don’t match though, it’s possible to provide this connection explicitly, as illustrated in the following code sample:
Alternatively the same connection could be made in the view, using an overload of Html.PropertyFor:
As the above makes clear, just because we are utilising a CMS product for our website is no reason that we have to leave behind some best practices we’ve come to use and value when working directly with ASP.Net MVC. Whether the benefits outweigh the small amount of additional effort required for a given project is something that anyone working with these platforms will need to consider. Both CMS platforms though provide a means of taking full control of the page rendering process, meaning the views can work with simple POCO view models designed to precisely model the information that needs to be presented.
Originally published at medium.com.