diff --git a/src/Umbraco.Tests/PublishedContent/RootNodeTests.cs b/src/Umbraco.Tests/PublishedContent/RootNodeTests.cs
new file mode 100644
index 0000000000..ceefbbc847
--- /dev/null
+++ b/src/Umbraco.Tests/PublishedContent/RootNodeTests.cs
@@ -0,0 +1,76 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using NUnit.Framework;
+using umbraco;
+using umbraco.MacroEngines;
+using Umbraco.Web;
+using Umbraco.Web.Models;
+using Umbraco.Web.Security;
+
+namespace Umbraco.Tests.PublishedContent
+{
+ [TestFixture]
+ public class RootNodeTests : PublishedContentTestBase
+ {
+ [Test]
+ public void PublishedContentHasNoRootNode()
+ {
+ var ctx = GetUmbracoContext("/test", 1234);
+
+ // there is no content node with ID -1
+ var content = ctx.ContentCache.GetById(-1);
+ Assert.IsNull(content);
+
+ // content at root has null parent
+ content = ctx.ContentCache.GetById(1046);
+ Assert.IsNotNull(content);
+ Assert.AreEqual(1, content.Level);
+ Assert.IsNull(content.Parent);
+
+ // and yet is has siblings, etc.
+ var siblings = content.Siblings();
+ Assert.AreEqual(2, siblings.Count());
+
+ // non-existing content is null
+ content = ctx.ContentCache.GetById(666);
+ Assert.IsNull(content);
+ }
+
+ [Test]
+ public void LegacyDynamicNodeSortOfHasRootNode()
+ {
+ // there is a node with ID -1
+ var node = new DynamicNode(-1);
+ Assert.IsNotNull(node);
+ Assert.AreEqual(-1, node.Id);
+
+ // content at root
+ node = new DynamicNode(1046);
+ Assert.IsNotNull(node);
+ Assert.AreEqual(1, node.Level);
+
+ // has no parent
+ // (confirmed in 4.7 and 6.1)
+ Assert.IsNull(node.Parent);
+
+ // has siblings etc - no idea how we're supposed to get them?
+ //var siblings = node.Parent.Children;
+ //Assert.AreEqual(2, siblings.Count());
+
+ // non-existing content is "zero node"
+ node = new DynamicNode(666, DynamicBackingItemType.Content); // set type to avoid Examine in tests
+ Assert.IsNotNull(node);
+ Assert.AreEqual(0, node.Id);
+ }
+
+ [Test]
+ public void Fix_U4_4374()
+ {
+ var node = new DynamicNode(-1);
+ var id = node.DescendantsOrSelf().First().Id;
+ Assert.AreEqual(-1, id);
+ }
+ }
+}
diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj
index b8736f8695..59e79eee6a 100644
--- a/src/Umbraco.Tests/Umbraco.Tests.csproj
+++ b/src/Umbraco.Tests/Umbraco.Tests.csproj
@@ -287,6 +287,7 @@
+
diff --git a/src/Umbraco.Web/umbraco.presentation/CompatibilityHelper.cs b/src/Umbraco.Web/umbraco.presentation/CompatibilityHelper.cs
index ca6b420e54..9aa57012af 100644
--- a/src/Umbraco.Web/umbraco.presentation/CompatibilityHelper.cs
+++ b/src/Umbraco.Web/umbraco.presentation/CompatibilityHelper.cs
@@ -57,7 +57,7 @@ namespace Umbraco.Web.umbraco.presentation
public INode Parent
{
- get { return ConvertToNode(_doc.Parent); }
+ get { return _doc.Parent == null ? null : ConvertToNode(_doc.Parent); }
}
public int Id { get; private set; }
public int template { get; private set; }
diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/nodeFactory/Node.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/nodeFactory/Node.cs
index 0373667939..954d36f699 100644
--- a/src/Umbraco.Web/umbraco.presentation/umbraco/nodeFactory/Node.cs
+++ b/src/Umbraco.Web/umbraco.presentation/umbraco/nodeFactory/Node.cs
@@ -301,7 +301,12 @@ namespace umbraco.NodeFactory
_pageXmlNode = ((IHasXmlNode)library.GetXmlNodeById(NodeId.ToString()).Current).GetNode();
else
{
- if (presentation.UmbracoContext.Current != null)
+ if (UmbracoContext.Current != null)
+ {
+ var cache = UmbracoContext.Current.ContentCache.InnerCache as Umbraco.Web.PublishedCache.XmlPublishedCache.PublishedContentCache;
+ _pageXmlNode = cache.GetXml(UmbracoContext.Current, false).DocumentElement;
+ }
+ else if (presentation.UmbracoContext.Current != null)
{
_pageXmlNode = umbraco.presentation.UmbracoContext.Current.GetXml().DocumentElement;
}
diff --git a/src/umbraco.MacroEngines/RazorDynamicNode/DynamicBackingItem.cs b/src/umbraco.MacroEngines/RazorDynamicNode/DynamicBackingItem.cs
index ded21a3119..d841f9ce3a 100644
--- a/src/umbraco.MacroEngines/RazorDynamicNode/DynamicBackingItem.cs
+++ b/src/umbraco.MacroEngines/RazorDynamicNode/DynamicBackingItem.cs
@@ -34,9 +34,8 @@ namespace umbraco.MacroEngines
{
if (Id == -1)
{
- //this is a special check, previously passing in -1 would return a real node, the root node. Though
- // it has no properties (defaults apply), you could access descendants, children, etc...
- //This is how this used to work before a large refactor - which I think may have broken other legacy logic too :(
+ // passing in -1 needs to return a real node, the "root" node, which has no
+ // properties (defaults apply) but can be used to access descendants, children, etc.
this.content = new NodeFactory.Node(Id);
return;
@@ -69,9 +68,8 @@ namespace umbraco.MacroEngines
{
if (Id == -1)
{
- //this is a special check, previously passing in -1 would return a real node, the root node. Though
- // it has no properties (defaults apply), you could access descendants, children, etc...
- //This is how this used to work before a large refactor - which I think may have broken other legacy logic too :(
+ // passing in -1 needs to return a real node, the "root" node, which has no
+ // properties (defaults apply) but can be used to access descendants, children, etc.
this.content = new NodeFactory.Node(Id);
}