The Umbraco Foundation – A dynamic journey of concerns

"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

%d bloggers like this: