"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:
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?:
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:
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 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