Some handy extension methods for IPublishedContent
Umbraco 6.x MVC added a new querying API that revolves around the IPublishedContent interface. This interface defines common properties and methods that a single content "node" is comprised of.
Properties include standard things like the Id and Name of the content, the CreateDate and also a collection of any custom properties. Methods include traversal functions that allow you to get all the Children() or Ancestors() of the current node. Interestingly, many of these are implemented as extension methods in the static class Umbraco.Web.PublishedContentExtensions. This then naturally leads us to the realisation that we can extend Umbraco by adding our own extension methods to IPublishedContent. All we need to do is create a static class and add it either as a part of a class library or (even more simply) put it in App_Code.
I've created a few a useful methods that I use myself that I'd like to share below. Most of these revolve around the idea that you often want to filter out certain nodes when generating things like navigation and menus. Whilst Umbraco supports the convention of a property called "umbracoNaviHide" (that manifests itself as the method IsVisible()) there are other common cases where you might want to exclude nodes from menus. For example, you generally don't want to have pages that haven't been assigned a template in your navigation as they will invariably lead to a 404 Not Found if served.
So, for instance, if you wanted to get all the child nodes of your home page that are not hidden from the menu you might write a query like this:
var menuItems = Model.Content.AncestorOrSelf(1).Children(x => x.IsVisible());
If you wished to extend this to also exclude nodes that don't have a template it would look like this:
var menuItems = Model.Content.AncestorOrSelf(1).Children(x => x.IsVisible() && x.TemplateId > 0);
As you can see this is getting a little unwieldy. Wouldn't it be nicer if we could rewrite this query as:
var menuItems = Model.Content.HomePage().Children().Where(x => x.IsInMenu());
Well, thanks to the wonder of extension methods you can! I've included some examples below that include these, but it's easy to come up with your own, too!
Umbraco Extensions C#
Tip: Accessing From Any View
To make extension methods accessible from any Razor View you can add your namespaces to the web.config folder inside your Views folder (not the main web.config).
<system.web.webPages.razor> <host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=220.127.116.11, Culture=neutral, PublicKeyToken=31BF3856AD364E35" /> <pages pageBaseType="System.Web.Mvc.WebViewPage"> <namespaces> <!-- Core Umbraco References --> <add namespace="System.Web.Mvc" /> <add namespace="System.Web.Mvc.Ajax" /> <add namespace="System.Web.Mvc.Html" /> <add namespace="System.Web.Routing" /> <add namespace="Umbraco.Web" /> <add namespace="Umbraco.Core" /> <add namespace="Umbraco.Core.Models" /> <add namespace="Umbraco.Web.Mvc" /> <add namespace="umbraco" /> <add namespace="Examine" /> <!-- Custom Namespace --> <add namespace="MyNameSpace.UmbracoExtensions" /> </namespaces> </pages> </system.web.webPages.razor>