From 73e9ff04e80df4bb1aac610c7b78ad394d0266cc Mon Sep 17 00:00:00 2001 From: Shannon Date: Fri, 2 Jan 2015 15:34:51 +1100 Subject: [PATCH] Fixes: U4-5943 Cannot render a macro on a virtual page when using UmbracoVirtualNodeRouteHandler and assigning virtual Ids --- .../Macros/PartialViewMacroEngine.cs | 8 +- src/Umbraco.Web/Models/LegacyConvertedNode.cs | 182 ++++++++++++++++++ .../Models/LegacyConvertedNodeProperty.cs | 54 ++++++ src/Umbraco.Web/Models/LegacyNodeHelper.cs | 25 +++ src/Umbraco.Web/Umbraco.Web.csproj | 4 +- .../CompatibilityHelper.cs | 163 ---------------- src/Umbraco.Web/umbraco.presentation/macro.cs | 16 +- .../RazorDynamicNode/DynamicBackingItem.cs | 5 +- 8 files changed, 284 insertions(+), 173 deletions(-) create mode 100644 src/Umbraco.Web/Models/LegacyConvertedNode.cs create mode 100644 src/Umbraco.Web/Models/LegacyConvertedNodeProperty.cs create mode 100644 src/Umbraco.Web/Models/LegacyNodeHelper.cs delete mode 100644 src/Umbraco.Web/umbraco.presentation/CompatibilityHelper.cs diff --git a/src/Umbraco.Web/Macros/PartialViewMacroEngine.cs b/src/Umbraco.Web/Macros/PartialViewMacroEngine.cs index 13267dd241..d1a435e48e 100644 --- a/src/Umbraco.Web/Macros/PartialViewMacroEngine.cs +++ b/src/Umbraco.Web/Macros/PartialViewMacroEngine.cs @@ -12,6 +12,7 @@ using Umbraco.Core.IO; using umbraco.cms.businesslogic.macro; using Umbraco.Core.Models; using umbraco.interfaces; +using Umbraco.Web.Models; using Umbraco.Web.Mvc; using Umbraco.Core; using System.Web.Mvc.Html; @@ -102,7 +103,12 @@ namespace Umbraco.Web.Macros public string Execute(MacroModel macro, INode node) { var umbCtx = _getUmbracoContext(); - return Execute(macro, umbCtx.ContentCache.GetById(node.Id)); + //NOTE: This is a bit of a nasty hack to check if the INode is actually already based on an IPublishedContent + // (will be the case when using LegacyConvertedNode ) + return Execute(macro, + (node is IPublishedContent) + ? (IPublishedContent)node + : umbCtx.ContentCache.GetById(node.Id)); } public string Execute(MacroModel macro, IPublishedContent content) diff --git a/src/Umbraco.Web/Models/LegacyConvertedNode.cs b/src/Umbraco.Web/Models/LegacyConvertedNode.cs new file mode 100644 index 0000000000..b2f5712364 --- /dev/null +++ b/src/Umbraco.Web/Models/LegacyConvertedNode.cs @@ -0,0 +1,182 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using Umbraco.Core.Models; +using Umbraco.Core.Models.PublishedContent; +using umbraco.interfaces; + +namespace Umbraco.Web.Models +{ + /// + /// A legacy INode that wraps IPublishedContent + /// + internal class LegacyConvertedNode : PublishedContentWrapped, INode + { + private readonly IPublishedContent _publishedContent; + private readonly int _id; + private readonly int _template; + private readonly int _sortOrder; + private readonly string _name; + private readonly string _urlName; + private readonly string _nodeTypeAlias; + private readonly string _writerName; + private readonly string _creatorName; + private readonly int _writerId; + private readonly int _creatorId; + private readonly string _path; + private readonly DateTime _createDate; + private readonly DateTime _updateDate; + private readonly Guid _version; + private readonly int _level; + + public LegacyConvertedNode(IPublishedContent publishedContent) : base(publishedContent) + { + _publishedContent = publishedContent; + + if (publishedContent == null) + { + _id = 0; + return; + } + + _template = publishedContent.TemplateId; + _id = publishedContent.Id; + _path = publishedContent.Path; + _creatorName = publishedContent.CreatorName; + _sortOrder = publishedContent.SortOrder; + _updateDate = publishedContent.UpdateDate; + _name = publishedContent.Name; + _nodeTypeAlias = publishedContent.DocumentTypeAlias; + _createDate = publishedContent.CreateDate; + _creatorId = publishedContent.CreatorId; + _level = publishedContent.Level; + _urlName = publishedContent.UrlName; + _version = publishedContent.Version; + _writerId = publishedContent.WriterId; + _writerName = publishedContent.WriterName; + } + + INode INode.Parent + { + get { return _publishedContent.Parent == null ? null : LegacyNodeHelper.ConvertToNode(_publishedContent.Parent); } + } + + int INode.Id + { + get { return _id; } + } + + int INode.template + { + get { return _template; } + } + + int INode.SortOrder + { + get { return _sortOrder; } + } + + string INode.Name + { + get { return _name; } + } + + string INode.UrlName + { + get { return _urlName; } + } + + string INode.NodeTypeAlias + { + get { return _nodeTypeAlias; } + } + + string INode.WriterName + { + get { return _writerName; } + } + + string INode.CreatorName + { + get { return _creatorName; } + } + + int INode.WriterID + { + get { return _writerId; } + } + + int INode.CreatorID + { + get { return _creatorId; } + } + + string INode.Path + { + get { return _path; } + } + + DateTime INode.CreateDate + { + get { return _createDate; } + } + + DateTime INode.UpdateDate + { + get { return _updateDate; } + } + + Guid INode.Version + { + get { return _version; } + } + + string INode.NiceUrl + { + get { return _publishedContent.Url; } + } + + string INode.Url + { + get { return _publishedContent.Url; } + } + + int INode.Level + { + get { return _level; } + } + + List INode.PropertiesAsList + { + get { return _publishedContent.Properties.Select(LegacyNodeHelper.ConvertToNodeProperty).ToList(); } + } + + List INode.ChildrenAsList + { + get { return _publishedContent.Children.Select(LegacyNodeHelper.ConvertToNode).ToList(); } + } + + IProperty INode.GetProperty(string alias) + { + return ((INode)this).PropertiesAsList.Cast().FirstOrDefault(p => p.Alias == alias); + } + + IProperty INode.GetProperty(string alias, out bool propertyExists) + { + var prop = _publishedContent.GetProperty(alias); + propertyExists = prop != null; + return prop == null ? null : LegacyNodeHelper.ConvertToNodeProperty(prop); + } + + DataTable INode.ChildrenAsTable() + { + return _publishedContent.ChildrenAsTable(); + } + + DataTable INode.ChildrenAsTable(string nodeTypeAliasFilter) + { + return _publishedContent.ChildrenAsTable(nodeTypeAliasFilter); + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Web/Models/LegacyConvertedNodeProperty.cs b/src/Umbraco.Web/Models/LegacyConvertedNodeProperty.cs new file mode 100644 index 0000000000..17ca6a39cc --- /dev/null +++ b/src/Umbraco.Web/Models/LegacyConvertedNodeProperty.cs @@ -0,0 +1,54 @@ +using System; +using System.Web; +using Umbraco.Core.Models; +using umbraco.interfaces; + +namespace Umbraco.Web.Models +{ + /// + /// A legacy IProperty that wraps IPublishedProperty + /// + internal class LegacyConvertedNodeProperty : IProperty, IHtmlString + { + public IPublishedProperty PublishedProperty { get; private set; } + + public LegacyConvertedNodeProperty(IPublishedProperty prop) + { + PublishedProperty = prop; + } + + public string Alias + { + get { return PublishedProperty.PropertyTypeAlias; } + } + + public string Value + { + get { return PublishedProperty.DataValue == null ? null : PublishedProperty.DataValue.ToString(); } + } + + public Guid Version + { + get { return Guid.Empty; } + } + + public bool IsNull() + { + return Value == null; + } + + public bool HasValue() + { + return PublishedProperty.HasValue; + } + + public int ContextId { get; set; } + public string ContextAlias { get; set; } + + // implements IHtmlString.ToHtmlString + public string ToHtmlString() + { + return Value; + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Web/Models/LegacyNodeHelper.cs b/src/Umbraco.Web/Models/LegacyNodeHelper.cs new file mode 100644 index 0000000000..6a102e54c8 --- /dev/null +++ b/src/Umbraco.Web/Models/LegacyNodeHelper.cs @@ -0,0 +1,25 @@ +using Umbraco.Core.Models; +using umbraco.interfaces; + +namespace Umbraco.Web.Models +{ + /// + /// Used to convert to/from the legacy INode from IPublishedContent + /// + internal static class LegacyNodeHelper + { + // NOTE - moved from umbraco.MacroEngines to avoid circ. references + + public static INode ConvertToNode(IPublishedContent doc) + { + var node = new LegacyConvertedNode(doc); + return node; + } + + public static IProperty ConvertToNodeProperty(IPublishedProperty prop) + { + return new LegacyConvertedNodeProperty(prop); + } + + } +} diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 7e649e4246..ccb7b12cd2 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -268,6 +268,8 @@ + + @@ -739,7 +741,7 @@ - + ASPXCodeBehind diff --git a/src/Umbraco.Web/umbraco.presentation/CompatibilityHelper.cs b/src/Umbraco.Web/umbraco.presentation/CompatibilityHelper.cs deleted file mode 100644 index 9aa57012af..0000000000 --- a/src/Umbraco.Web/umbraco.presentation/CompatibilityHelper.cs +++ /dev/null @@ -1,163 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Data; -using System.Linq; -using System.Text; -using System.Web; -using Umbraco.Core.Models; -using umbraco.interfaces; - -namespace Umbraco.Web.umbraco.presentation -{ - static class CompatibilityHelper - { - // NOTE - moved from umbraco.MacroEngines to avoid circ. references - - public static INode ConvertToNode(IPublishedContent doc) - { - var node = new ConvertedNode(doc); - return node; - } - - private static IProperty ConvertToNodeProperty(IPublishedProperty prop) - { - return new ConvertedProperty(prop); - } - - private class ConvertedNode : INode - { - private readonly IPublishedContent _doc; - - public ConvertedNode(IPublishedContent doc) - { - _doc = doc; - - if (doc == null) - { - Id = 0; - return; - } - - template = doc.TemplateId; - Id = doc.Id; - Path = doc.Path; - CreatorName = doc.CreatorName; - SortOrder = doc.SortOrder; - UpdateDate = doc.UpdateDate; - Name = doc.Name; - NodeTypeAlias = doc.DocumentTypeAlias; - CreateDate = doc.CreateDate; - CreatorID = doc.CreatorId; - Level = doc.Level; - UrlName = doc.UrlName; - Version = doc.Version; - WriterID = doc.WriterId; - WriterName = doc.WriterName; - } - - public INode Parent - { - get { return _doc.Parent == null ? null : ConvertToNode(_doc.Parent); } - } - public int Id { get; private set; } - public int template { get; private set; } - public int SortOrder { get; private set; } - public string Name { get; private set; } - public string UrlName { get; private set; } - public string NodeTypeAlias { get; private set; } - public string WriterName { get; private set; } - public string CreatorName { get; private set; } - public int WriterID { get; private set; } - public int CreatorID { get; private set; } - public string Path { get; private set; } - public DateTime CreateDate { get; private set; } - public DateTime UpdateDate { get; private set; } - public Guid Version { get; private set; } - - public string NiceUrl - { - get { return _doc.Url; } - } - - public string Url - { - get { return _doc.Url; } - } - - public int Level { get; private set; } - public List PropertiesAsList - { - get { return _doc.Properties.Select(ConvertToNodeProperty).ToList(); } - } - public List ChildrenAsList - { - get { return _doc.Children.Select(ConvertToNode).ToList(); } - } - public IProperty GetProperty(string alias) - { - return PropertiesAsList.Cast().FirstOrDefault(p => p.Alias == alias); - } - - public IProperty GetProperty(string alias, out bool propertyExists) - { - var prop = _doc.GetProperty(alias); - propertyExists = prop != null; - return prop == null ? null : ConvertToNodeProperty(prop); - } - - public DataTable ChildrenAsTable() - { - return _doc.ChildrenAsTable(); - } - - public DataTable ChildrenAsTable(string nodeTypeAliasFilter) - { - return _doc.ChildrenAsTable(nodeTypeAliasFilter); - } - } - - private class ConvertedProperty : IProperty, IHtmlString - { - private readonly IPublishedProperty _prop; - - public ConvertedProperty(IPublishedProperty prop) - { - _prop = prop; - } - - public string Alias - { - get { return _prop.PropertyTypeAlias; } - } - - public string Value - { - get { return _prop.DataValue == null ? null : _prop.DataValue.ToString(); } - } - - public Guid Version - { - get { return Guid.Empty; } - } - - public bool IsNull() - { - return Value == null; - } - - public bool HasValue() - { - return _prop.HasValue; - } - - public int ContextId { get; set; } - public string ContextAlias { get; set; } - - // implements IHtmlString.ToHtmlString - public string ToHtmlString() - { - return Value; - } - } - } -} diff --git a/src/Umbraco.Web/umbraco.presentation/macro.cs b/src/Umbraco.Web/umbraco.presentation/macro.cs index cdb8736952..42c3dbe05d 100644 --- a/src/Umbraco.Web/umbraco.presentation/macro.cs +++ b/src/Umbraco.Web/umbraco.presentation/macro.cs @@ -29,6 +29,7 @@ using umbraco.interfaces; using Umbraco.Web; using Umbraco.Web.Cache; using Umbraco.Web.Macros; +using Umbraco.Web.Models; using Umbraco.Web.Templates; using umbraco.BusinessLogic; using umbraco.cms.businesslogic.macro; @@ -1556,13 +1557,13 @@ namespace umbraco if (currentNodeProperty != null && currentNodeProperty.CanWrite && currentNodeProperty.PropertyType.IsAssignableFrom(typeof(Node))) { - currentNodeProperty.SetValue(control, Node.GetCurrent(), null); + currentNodeProperty.SetValue(control, GetCurrentNode(), null); } currentNodeProperty = type.GetProperty("currentNode"); if (currentNodeProperty != null && currentNodeProperty.CanWrite && currentNodeProperty.PropertyType.IsAssignableFrom(typeof(Node))) { - currentNodeProperty.SetValue(control, Node.GetCurrent(), null); + currentNodeProperty.SetValue(control, GetCurrentNode(), null); } } @@ -1846,10 +1847,13 @@ namespace umbraco private static INode GetCurrentNode() { - var id = Node.getCurrentNodeId(); - var content = UmbracoContext.Current.ContentCache.GetById(id); - //TODO: This should check for null! - return CompatibilityHelper.ConvertToNode(content); + //Get the current content request + + var content = UmbracoContext.Current.PublishedContentRequest != null + ? UmbracoContext.Current.PublishedContentRequest.PublishedContent + : null; + + return content == null ? null : LegacyNodeHelper.ConvertToNode(content); } #region Events diff --git a/src/umbraco.MacroEngines/RazorDynamicNode/DynamicBackingItem.cs b/src/umbraco.MacroEngines/RazorDynamicNode/DynamicBackingItem.cs index d841f9ce3a..cde2fd793f 100644 --- a/src/umbraco.MacroEngines/RazorDynamicNode/DynamicBackingItem.cs +++ b/src/umbraco.MacroEngines/RazorDynamicNode/DynamicBackingItem.cs @@ -10,6 +10,7 @@ using System.Data; using Umbraco.Core; using umbraco.MacroEngines.Library; using Umbraco.Web; +using Umbraco.Web.Models; using Umbraco.Web.umbraco.presentation; namespace umbraco.MacroEngines @@ -41,7 +42,7 @@ namespace umbraco.MacroEngines return; } - var n = CompatibilityHelper.ConvertToNode(UmbracoContext.Current.ContentCache.GetById(Id)); + var n = LegacyNodeHelper.ConvertToNode(UmbracoContext.Current.ContentCache.GetById(Id)); this.content = n; this.Type = DynamicBackingItemType.Content; @@ -75,7 +76,7 @@ namespace umbraco.MacroEngines } else { - this.content = CompatibilityHelper.ConvertToNode(UmbracoContext.Current.ContentCache.GetById(Id)); + this.content = LegacyNodeHelper.ConvertToNode(UmbracoContext.Current.ContentCache.GetById(Id)); } this.Type = Type;