Umbraco 4.5 a quick guide (inc Linq to Umbraco tip)

July 22, 2010

Whilst working on my first big Umbraco 4.5 implementation I began noticing the new preview functionality didn’t behave as I expected.

To start off with I thought it was broken, but in fact there are some performance related decisions that have been made in the implementation that can confuse you when you first start using it.

First off how does Preview work:

The new Umbraco preview functionality generates a new XML cache of the Umbraco content when you press the preview button and uses this whilst you are browsing the site in preview mode.

However to aid performance Umbraco only generates preview data for the nodes including and below the one you are previewing. They do this for performance reasons. However this can lead to some unexpected behaviour if you are using recursive data in your macros etc (Data which is stored higher in the tree than the node you are previewing).

The solution to this is of course to preview your site starting from the homepage, then the full node tree is populated with preview data when you press preview (this could get slow in big sites).

Preview works perfectly with NodeFactory and with XSLT as long as you bear the above in mind.

The other quirk that had me stumped for ages and made me think preview was broken was Linq2Umbraco. Linq to Umbraco staunchly failed to show preview content. So I had a dig about in the 4.5 source and discovered that the default provider for Linq to Umbraco ONLY USES PUBLISHED DATA.

However the clever folk at Umbraco have given us a way to make this work (they just haven’t told us 😉 )

The answer is in the code below:

namespace Extensions.LinqToUmbraco
{
    using System;
    using System.Web;
    using umbraco.presentation;
    using umbraco.presentation.preview;
    using umbraco.Linq.Core.Node;

    /// <summary>
    /// Extension class which provides singleton like access to the UmbracoNodesDataContext
    /// It is not a true singleton pattern, but is ueful because it provides HttpContext
    /// level caching of Umbraco data, improving performance on requests
    /// </summary>
    public partial class UmbracoNodesDataContext
    {
        /// <summary>
        /// Instance property which creates a new instance of the UmbracoNodesDataContext class
        /// if the instance has already been created within the current HttpContext then it returns the cached version.
        /// However if the site is in preview mode then it returns the current preview content (this is not cached in the HttpContext)
        /// </summary>
        public static UmbracoNodesDataContext Instance
        {
            get
            {
                var context = HttpContext.Current.Items["UmbracoNodesDataContex"] as UmbracoNodesDataContext;

                if (UmbracoContext.Current.InPreviewMode)
                {
                    var previewContent = new PreviewContent(new Guid(umbraco.BusinessLogic.StateHelper.GetCookieValue("PreviewSet")));
                    var path = previewContent.PreviewsetPath;
                    context = new UmbracoNodesDataContext(new NodeDataProvider(path, true));
                }
                else
                {
                    if (context == null)
                    {
                        context = new UmbracoNodesDataContext();
                        HttpContext.Current.Items["UmbracoNodesDataContext"] = context;
                    }
                }

                return context;
            }
        }
    }
}
The above code is a partial calss which extends the DataContext which is auto generated by Linq2Umbraco. It needs to be in the same nasespace as your main DataContext class and have the same class name.
More info on partial classes here: http://msdn.microsoft.com/en-us/library/wa80x488(VS.80).aspx
It does 2 things, the first is to implement a singleton type pattern so your datacontext can be cached during the current HttpContext, which should give you a performance boost (as outlined in this video: http://vimeo.com/9790069)
It also checks to see if the site is in preview mode and if it is grabs the preview XML and passes that to the NodeDataProvider. This means that when in preview mode Linq2SQL will behave just like Nodefactory and XSLT and sow the preview content. I’m not caching the preview content in the current context BTW.
Till next time.

2 Responses to “Umbraco 4.5 a quick guide (inc Linq to Umbraco tip)”

  1. Stefan Kip Says:

    Very nice blogpost!
    Thanks!

  2. Aaron Powell Says:

    You’ll be happy to know that 4.5.1 will include LINQ to Umbraco which supports preview.


Leave a comment