Virtually every website has to have some form of navigation. Most, also have sub navigation, and these may drill down several levels. Most commonly, the site navigation is written so that it reflects the content in the Umbraco admin area. So, the top level would be 'Home', followed by (say), 'About Us', 'Contact Us', 'Products', 'Fees'. Obviously, these are just examples.... In this instance, 'Home' is the 'top level', followed by the other pages (1st level). If there are sub-pages in (say) Products, then these will become '2nd level navigation'. And if those pages also had 'sub-pages', then that would be '3rd level navigation'.... and so on....
It is common to write some Razor code which loops through the Umbraco 'parent/child' nodes and writes the website navigation from the results. Indeed, if you use the 'code snippet' kindly supplied by Umbraco, it will create navigation this way.
Which is fine until the your site becomes complex, and keeping the pages in a decent 'parent/child' order, increasingly difficult. Eventually, a content editor will publish a page in the wrong place and the website navigation goes 'pearshaped' - you can guarantee it!
But, what is the alternative?
My preferred choice is to create a docType 'Site Settings', into which I then create a tab 'Navigation'. Then, I create 'Top Links', 'Footer Links', and 'Secondary Nav', all of which use the 'MultiNodeTreePicker' - which effectively allows nodes to be selected as links.
In addition, I add a 'mulitnodetreepicker' to the docType of a standard page.
The net result of all this, is instead of a navigation system which simply loops through the Umbraco content tree, you have the ability to select what appears in the displayed navigation, from the top level, through to many lower levels. With the pages being linked to in the navigation being selected, rather than automatically linked to. A system which is more refined and less prone to mistakes.
Of course, once you have set up your navigation pickers in the docTypes, you then have to extract the selected pages from the Umbraco API. Often, this is done as razor code in a partial view. This works, and it is easier to create the 'loops with loop' required to create the required multi level navigation. However, because it is 'Razor' code, rather than a compiled 'Controller, model, view', the code needs to be called every time a page (with navigation) is displayed. This can slow your website down.
A much better method is to put all the code into a 'controller' or 'surface controller', which is compiled and cached. It can be stored in memory and then called when required. However, what stops this method being used more often, is the thorny issue of 'looping' through a 'multinodetreepicker', whilst actually being already in a 'loop'. An array within an array, if you like...
It took me a while to work out a stable solution to this problem, but I got there in the end. Which is something we will look at in the next article!