Using Razor in Umbraco 4.7

How to use strongly-typed Razor macros in Umbraco 4.7x with intellisense support

One of the major new things added to Umbraco recently was the ability to use the new Razor view engine to create macros within Umbraco. This allows developers to utilise the same scripting-language syntax (C# or VB.NET) that is becoming common-place in ASP.NET MVC and Microsoft WebMatrix. In other words, Razor offers a direct alternative to using XSLT to present content within Umbraco. In fact, some people believe that Razor will entirely replace XSLT as the primary means of displaying content - this has even led to the formation of the XSLT Rebel Alliance! But that is an argument for another day... :)

However, if you've never used Razor with Umbraco then you may well be confused as to where to start (I know I was). You'll probably search Google and find a number of blog posts about it, only to discover that the way Razor has been implemented in Umbraco has changed a lot between its initial release in 4.6 to where it is today in 4.7x releases. This can only add to the confusion.

Help! I'm Lost

OK, so, what I aim to do in this blog post is achieve two small objectives:

  1. Help you get started using Razor with Umbraco 4.7.
  2. Show you how to use strongly-typed models in Razor with full Visual Studio intellisense support.

Note: This isn't a tutorial on using Razor - there are plenty of those around you can find.

How to Create and use Razor Macros in Umbraco 4.7

As mentioned, Razor is a direct alternative to using XSLT macros to present content. As you probably know, there are two stages to creating an XSLT macro: first you create your XSLT file and then you create the macro to contain it. However, in Razor you simply create one script (sometimes known as a view) that implements both the scripting-language and the macro. But how do you actually do this in the Umbraco back-end?

Creating a Razor Script

To create a new Razor script (view) in Umbraco 4.7 you need to go to the Developer section and then to the new Scripting Files folder shown in the tree. You can then right-click the Scripting Files folder and select the Create menu option :

Developer - Create Razor Script

This will then open the new Create Razor Macro dialogue as below:

Create Razor Script

You get two choices of Razor Macro Engine - Cshtml and Vbshtml. The perceptive among you should have realised the names give you a clue as to what the difference between these is; but in case you haven't guessed the former sets up scripting in the view to use C# and the latter to use VB.NET.

You can also select a default script template to create (analogous to the way you can when creating a new XSLT script). This is a simple predefined template for common taks, such as creating a breadcrumb trail or listing pages. I'll talk more about this later.

Once you have created your script you can then edit the content within Umbraco or open the file in Visual Studio (it will be in the /macroScripts folder). I'll give you some tips on this later in this post.

Adding the Razor Macro to a Template

OK, now you've created your Razor script macro, but how do you add it to a template? Well, this is easy - you add it in exactly the same way as you add a normal Umbraco macro. Open up the template you want to add the macro to and then use the nifty (new and improved) Macro selector as so:

Insert Razor Macro

Of course, you can simply type the mark-up directly into the template, too:

Razor Macro in Template

<umbraco:Macro Alias="RazorMacroAlias" runat="server" />

As you can see, the mark-up for a Razor macro is the same as for an XSLT or User Control macro. Just remember, like any ASP.NET control, you need to add runat="server" for it to render!

If you've got this far then you should now be able to create a new Razor script macro and add it to a template. However, if you've tried to edit your .cshtml (or .vbhtml) script in Visual Studio you might be disappointed to notice that there is no intellisense auto-completion for your Model. Let's try and fix that...

How to Get Intellisense in Visual Studio working with a Razor Script in Umbraco

If you've used one of the example templates to create your Razor script you will see an example of the Razor syntax in action. For instance, if you've used the Breadcrumb template then you'll see mark-up like this:

@inherits umbraco.MacroEngines.DynamicNodeContext
  @foreach(var level in @Model.Ancestors().Where("Visible"))
    <li><a href="@level.Url">@level.Name</a></li>

If you're like me your first reaction to this will be:

  • Where's my intellisense on the Model ?
  • Why isn't it using strongly-typed lambda expressions like we normally use in LINQ?

Well, after some searching on the Umbraco forum I found out that you can use another variable called CurrentModel instead of Model and this does give you full intellisense and full strongly-typed LINQ lambda support using all your favourite IEnumerable extension methods.

So we can re-write the above breadcrumb script like this:

    @foreach(var level in @CurrentModel.Ancestors().Items.Where(i => i.Visible))
        <li><a href="@level.Url">@level.Name</a></li>

And we have full intellisense support in Visual Studio 2010 as shown below:

Razor Visual Studio Intellisense in Umbraco

Now isn't that much nicer?

Why the Two Types?

To understand more the difference between Model and CurrentModel we need to examine what their underlying type is. If you do you'll find that:

  • Model is of type dynamic
  • CurrentModel is of type umbraco.MacroEngines.DynamicNode

The dynamic type was introduced in .NET 4.0 and MSDN explains that:

"The dynamic type enables the operations in which it occurs to bypass compile-time type checking. Instead, these operations are resolved at run time."

So, if you think about it, it is impossible for intellisense to work with dynamic types as the compiler doesn't know what it is until it is resolved at runtime. The DynamicNode type, though, is a standard .NET type (created by the Umbraco devs) and thus instances of it act like any other object.

Advantages and Disadvantages

So, you might be thinking, why would I use Model when I can use the nice, strongly-typed CurrentModel with full intellisense support? Well, the big advantage of using a dynamic type is that it can fully reflect all the properties in the underlying Umbraco document-type you've created. For instance, if your document-type has a property alias called umbracoNaviHide then you can access this directly from your model like this:


However, you can't do that with CurrentModel because that is an instance of DynamicNode which is a .NET class that only knows about the standard properties of an Umbraco data-type, not any custom ones you may have added. To access the same property on CurrentModel you'd have to write this:


But actually these two aren't quite the same because the former returns boolean false where as the latter returns the exact value stored in the XML which is, in fact, a string containing the character 0.

Of course, either way you need to be careful when accessing custom properties because if the property doesn't exist (or you've mis-typed it) then you'll get a nasty run-time error. To be totally safe you can check the value first using the HasProperty method as below:

@if (@CurrentModel.HasProperty("umbracoNaviHide"))
    string value = CurrentModel.GetProperty("umbracoNaviHide").Value;

Further Reading

For more help on using Razor please check the Related Links section to the left of this post. I'll try and blog more about Razor in the future, too.

Posted: 17 June 2011 | Bookmark: Permalink | Comments: Post Comment | Follow: RSS Feed | Bookmark and Share |
Tagged: , , , | Social Tags: Microsoft Visual Studio, Template engines, Procedural programming languages, IntelliSense, XSL Transformations, ASP.NET, Macro (computer science), Scripting language, Visual Basic, Computing, Computer programming, Software engineering | Organisations: ASP.NET, VB.NET, Google, Microsoft | Cities: Reading

3 comments for “Using Razor in Umbraco 4.7”

  • Gravatar of Tom

    Brillant article and nicely written, just what i was after :)

    Keep up the razor bloging :)

  • Thank's for this well written article! You gave me what i needed! keep up with the good work :)

  • Gravatar of jadroman

    It's just super-duper article and super duper blog :D


Post a Comment

Please fill the form in below if you wish to add a comment:

Please don't post raw HTML - use editor above - otherwise you will get an error.