Umbraco won my developer’s heart. It’s the best example of how to set tasks and achieve them. In this article I made an overview of development basics and main concepts. Originally it was written in my Russian blog.
Umbraco meets developer’s reuiqrements of a true CMS completely. Infrastructure is built around concept of content documents and operations in which they are involved.
Document
Document is the fundamental of this CMS forming the very bones of it. Document types are the types of pages that can be published on website. They consist of custom set of fields. These fields are defined by specific data types that include data storage type and render control type in admin console. Fields can be stored in different tabs for ease of use.
Only several data types are available from DB point of view (Integer, Data, Ntext, Nvarchar). I didn’t check whether engine has to be recompiled in order to add new data types or not. These primitive types are coupled with logical and render types: you can define editor type or provide standard set of values that will be selected from a drop-down list. This selection may also define behaviour of data type rendering on output stage through ASP.NET templates or XSLT (later on that), but in the latter case you cane explicitly define not to escape HTML characters. There are 20 standard types that can cover most of use cases. New types can be easily added via Umbraco itself or creating and uploading new DLL that is compiled from just 3 classes (thx to Nibble) (although I didn’t check this yet).
When new document type is created a set of fields is defined for it. These fields can be split among custom categories that are added on ’Tabs’ eh... tab :-) These tabs will be rendered separately in admin GUI. Standard ’Generic Properties’ tab keeps properties that are common for all document types. Additional tabs should be used in order to categorize specific fields and increase ease site management.

Aliases and names can be applied to all entities in Umbraco. This is very important for document and field types: aliases are used to make type checks programmatically in C# or XSLT while names are just readable labels used in GUI. Additionally: icon and description can be set for any document type; document mark-up templates should be selected and child node types can be defined.
Templates are another part of Umbraco foundation. Starting from version 4 Umbraco utilizes ASP.NET master pages as templates. This is coupled by admin GUI being able to show templates dependencies as hierarchy thus making visual order management much easier (no more files garbage in tree-view). And what’s great is: Umbraco GUI provides easy means to add Content Placeholders and Content items with just a few clicks.

Any template defines page design and can use a bunch of helpful items: macros (XSLT, user controls and python modules), dictionary items (hello, localization) and document field values.
As a result we have logical division that is very important for development: data and rendering are separated, as well as functional items are separated into stand-alone controls. Note that we have all this using common ASP.NET without any MVC or MVVM. Yes, we don’t have testing and some other possibilities here, but we have many means to support from small-sized to middle-sized websites at least, and these are most cases when some general CMS should be used.
Macros
Umbraco provides simple and effective way to use macros. It uses .NET on maximum adding up some interoperability means.
Any document rendering can be achieved via XSLT, even pagination tasks. Of course you can create your own C# code coupled by user controls, but it would be wiser to use basic framework. Suppose you need to render all child documents of some specific type from some root document restricting them to 2nd level of nesting. For that purpose create XSLT file with macros (system will ask whether it has to create macros automatically) and implement following code there:
1: <?xml version="1.0" encoding="UTF-8"?>
2: <!DOCTYPE xsl:stylesheet [ <!ENTITY nbsp " "> ]>
3: <xsl:stylesheet
4: version="1.0"
5: xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
6: xmlns:msxml="urn:schemas-microsoft-com:xslt"
7: xmlns:umbraco.library="urn:umbraco.library"
8: exclude-result-prefixes="msxml umbraco.library">
9:
10:
11: <xsl:output method="xml" omit-xml-declaration="yes"/>
12:
13: <xsl:param name="currentPage"/>
14:
15: <xsl:template match="/">
16:
17: <xsl:variable name="rootTextpageNode"
select="$currentPage/ancestor-or-self::node
[@level = 2 and @nodeTypeAlias = 'CWS_Galleries']" />
18:
19: <div class="secondaryNav">
20: <h3>
21: <xsl:value-of select="$rootTextpageNode/@nodeName"/>
22: </h3>
23:
24: <ul>
25: <xsl:for-each select="$rootTextpageNode/node
[@nodeTypeAlias = 'CWS_Galleries']">
26: <li>
27: <xsl:if test="$currentPage/ancestor-or-self
::node/@id = current()/@id">
28: <xsl:attribute name="class">
29: <xsl:text>selected</xsl:text>
30: </xsl:attribute>
31: </xsl:if>
32:
33: <a href="{umbraco.library:NiceUrl(
current()/@id)}">
34: <span>
35: <xsl:value-of select="current()
/@nodeName"/>
36: </span>
37: </a>
38: </li>
39: </xsl:for-each>
40: </ul>
41: </div>
42:
43: </xsl:template>
44:
45: </xsl:stylesheet>
This script utilizes document attributes in its processing. There’s a bunch of common generic attributes, e. g., node name, id and level (nesting level). Also there’s useful Umbraco library available both in C# and XSLT. And one thing that is heavily used is building URLs to specific document. If you have document ‘Chairs’ that nests ‘Stool’ doc we could use direct URL:
http://site/chairs/common-stool.aspx
That’s pretty good already ’cause we can build URL based on nodes names. But there’s a much better way to get links:
href="{umbraco. library: NiceUrl(current()/@id)}"
We can use anything that can be used in XSLT plus several useful hints from Umbraco. We still have to do some common work to get AJAX using Umbraco, but developer is not restricted on how he can do this: you can select ASP.NET AJAX, jQuery, Dojo or anything else.
Visual Studio and any code development that involves user controls are needed only when some additional functionality is needed that cannot be provided by Umbraco. E. g.: email sending, requests to external systems and web services.
To make developer’s life easier on path of additional functions development common ASP.NET lifecycle works for all user controls. Controls are just added into templates. Umbraco do not throw monkey wrench into public properties processing and we can pass them down to our controls. Moreover, it helps to use them even more easily. Here’s another example how this is done.
First of all, let’s have some control with following properties (just a small bit of code here to make things clear):
public string EmailTo
{
get
{
return _EmailTo;
}
set
{
_EmailTo = value;
}
}
public string EmailSubject
{
get
{
return _EmailSubject;
}
set
{
_EmailSubject = value;
}
}
public string EmailBody
{
get
{
return _EmailBody;
}
set
{
_EmailBody = value;
}
}
* This source code was highlighted with Source Code Highlighter.
Next, when control has been copied into usercontrols/website directory we create new macro and select user control there. After this, clicking ’Properties’ button we get full list of all public properties we added. Just select those you need to be supported on pages:

We can provide almost any values needed in our templates or even specific pages this way:
<umbraco:Macro EmailTo="[#emailTo]"
EmailSubject="[#emailSubject]"
EmailBody="[#emailBody]"
EmailReplyFrom="[#emailReplyFrom]"
EmailReplySubject="[#emailReplySubject]"
EmailReplyBody="[#emailReplyBody]"
EnableSSL="[#enableSSL]"
FormHeader="[#headerText]"
FormText="[#formText]"
ThankYouHeaderText="[#thankYouHeaderText]"
ThankYouMessageText="[#thankYouMessageText]"
Alias="CWS_ContactForm" runat="server"></umbraco:Macro>
* This source code was highlighted with Source Code Highlighter.
These properties will be set from values defined for a specific page (remember those tabs) and passed to control instance where they can be used in any way.
Summary
Umbraco utilizes one of best principles: create once, use many times after (‘use anywhere’ is an idealistic view). Document workflow is coupled by great ease of development. But there’s one important condition required — good knowledge of ASP.NET tech. stack. Add up standard architecture principles that should be developed by team for uniformity of projects.
Most of tasks can be achieved in administration console. Any set of elements including developed user controls and additional libraries can be packed into modules (called packages in Umbraco) and easily added into new Umbraco installations.
Difficulties
There are only 2 main issues that concern system setup and can be a pain. First of all, Umbraco needs web-site root. It won’t work in any subfolder in separate application pool.
Another issue involves web. config files. Settings introduced in these files are inherited from parent folder to children. This can be easily fixed fir < system. web> node: just wrap in into < location> node with attribute inheritInChildApplications="false". But there’s no such solution for < configSection> node, and here Umbraco introduces many settings that can clash with other applications. In my case there was a problem with ScrewTurn Wiki. This engine uses ASP. NET AJAX extensions as well as Umbraco, but utilizing another version. Thus AJAX dependencies of Umbraco meet with dependencies of Wiki with same names and Wiki goes to 500. If I try to fix this for Wiki I get dead Umbraco. The only solution was to move Wiki into separate sub domain.
Uncovered topics
I haven’t researched how Umbraco solves localization in practice. But as I see its language dictionaries partially solves this problem. Dictionary keys-references can be included on templates. This is coupled by locale handling by ASP. NET.
I didn’t cover users’ management as well. Umbraco allows creating console users as well as web-site members. In both cases user rights management is supplied. I think that Umbraco framework provide all required info to templates and macros. But once again: practice required here. To this I can add that Active Directory integration is pretty easy and AD provider is available.
Back- and Front-Office
Decisions on how to separate functions between administration console and web-site can vary. But anyway I think that console should not be covered with all special functions: anything related to users’ functions should be available on web-site itself. Why would common visitors care about any console? This way is supported by Umbraco API available in .NET. But web-site managers will definitely want all their tasks be achievable in console.
Creative Website Starter
One reason I could study Umbraco pretty fast was that I used Creative Website Starter (CWS) to develop my home site. During CWS ‘excavations’ I understood this uncommon and effective development Zen. What makes this especially funny is: I had spent almost an hour trying to find SQL scripts before I have understood how developer has to work with data here.
Feb. 12 2010 Update
Having almost half-a-year practice with Umbraco I’m still glad to work with this CMS. Everything is simple here.
If administrative console has to be extended new ascx-files are developed and added into usercontrols/dashboard directory of Umbraco installation. There data-processing can be made in any way: you just have to provide data logic that is used by some web-site controls as well. Here’s an example. User fills some form in web-site. Implemented user control saves this input in some custom data table in SQL Server or stores input into local xml file. In order to allow admin read this input we have to add admin user control that reads input from the same place where it was saved previously. Good example is available in CWS.
Another thing is standard processing of some data in documents. For that purpose we can create custom cs-file that contains event handlers wired to documents model. Events are wired in Page_Load event. Document events are described in Umbraco API object model. Then we upload this new file in App_Code directory in Umbraco root. Several files can be provided at a time. There’s a good example on Umbraco Web-site. Events can be peeped in object model with Visual Studio. In user control project several references are needed to use CMS API: businesslogic. dll, cms. dll и umbraco. dll.
And one bug: Umbraco handles Before-events after actual document changes so that we’re up to After-events only.