The Umbraco Foundation - A dynamic journey of concerns

Posted by Jeroen Wijdeven on 2014-03-25
The Macaw.Umbraco.Foundation is deprecated and I’am not involved in the development of this anymore. However we continue working on Muffin which is based on the same principles.

This post is a recap of a presentation I gave at the BUUG (The Belgium Umbraco User group) The presentation is available on Slideshare.

Why did I start developing the foundation?

Two of my main concerns when I dived a little deeper into the Umbraco system are:

  • The flexibility of Umbraco has it’s price. XSLT, Webforms, MVC where to start and what to use? I have seen solutions where all these techniques are used together. Resulting in a non-maintainable solution at the end.
  • I don’t like code ….. In VIEWS! How can we keep them front-end / non-Umbraco developer friendly?

For example the next line of code is very Umbraco specific:

GetPropertyValue in Umbraco

And the next piece of code looks more like a ViewModel declaration than actual view specific code.

object declarations in the view] in Umbraco

Let’s separate the concerns

  • Models are for business
  • Controllers are for interaction, and creating views
  • Views are templates where content and design come together

A great practice is “Single responsibility” or sometimes also called “Single point of failure”. Umbraco has some great solutions for that. IPropertyValueConverters for example prevent you to write a bunch of code everytime you try to convert your ContentPicker property to an IPublishedContent object. The property converter is called every time GetPropertyValue is exececuted. We have implement 4 converters in our foundation, which in our foundation also work for Macro properties (parameters).

  • ContentPicker returns an IPublishedContent, which usually returns an integer.
  • MediaPicker returns an url or a nice looking default image, which usually returns an integer aswell.
  • RelatedLinks returns a list of UrlModel objects, which usually returns some json (since v7).
  • MacroContainer returns a list of DynamicMacroModelHtmlProxies. This is a proxy for the DynamicMacroModel class and extend it with IHtmlString functionality. The DynamicMacroModel is a dynamic representation of a Macro object where the parameters are the properties. The IHtmlString functionality is the Umbraco tag for rendering the macro <?UMBRACO_MACRO .. />. Usually a MacroContainer property results in a HtmlString where all macros are merged together in one div container. Which a front-end developer don’t like because of the extra html and the Umbraco developer don’t like, because he doesn’t have any flexibility to manipulate the list. What about a Macro that looks like this?:

Separate the concerns

Simplefied views

The PropertyValueConvertes results in converted objects where you don’t have to convert those properties every time in your view. But simplified views mean a little more. And with a little I mean views with as less system dependency (like GetPropertyValue etc) as possible. In the end this can result in something like this:

Simplefied views

But where is the “GetPropertyValue” called in the Simplefied views example?

Suprise! That’s all about dynamics. By introducing a Dynamic”View”Model every TryGetMember call can excecute the GetPropertyValue. The best of it all; Umbraco has already done this with their DynamicPublishedContent. In our foundation we just write a proxy for the DynamicPublishedContent that add some extras like: a “Homepage” property and “Breadcrumbs”. This proxy is acting as our ViewModel.

The proxy

The foundation

The foundation mainly focussed on the concern of “clean” views. However the foundation is a lot more. Other important goals are:

  • Standarisation. By giving a set of best practices and implementation which can be used in other Umbraco projects as well.
  • Single responsibility. No (or as less as possible) duplicated code or implementations. This is mainly reached by doing separation of concerns right.
  • Improve overall quality. More testable code, single points of failure, caching etc..
  • Reducing development time. Don’t reinvent the wheel everytime. Standard blocks of implementation can help a lot.

Some features we haven’t talked about in this article are:

  • Paged list controllers
  • Json converters; Convert an IPubhlishedContent into a Json string.
  • Default full-text search implementation with Examine
  • IPublishedContent type mappers; Map an IPublishedContent to a typed ViewModel.
  • Translation helpers; Use default translation when item is not in dictionary
  • Standard Sitemap implementation

If you like to try it yourself go to: GitHub . The example project contains examples for every feature.

UPDATE 01-07-2015: Muffin (a fork of the foundation) is much more mature: Muffin