Fixes: U4-5943 Cannot render a macro on a virtual page when using UmbracoVirtualNodeRouteHandler and assigning virtual Ids

This commit is contained in:
Shannon
2015-01-02 15:34:51 +11:00
parent 201464cb44
commit 73e9ff04e8
8 changed files with 284 additions and 173 deletions

View File

@@ -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)

View File

@@ -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
{
/// <summary>
/// A legacy INode that wraps IPublishedContent
/// </summary>
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<IProperty> INode.PropertiesAsList
{
get { return _publishedContent.Properties.Select(LegacyNodeHelper.ConvertToNodeProperty).ToList(); }
}
List<INode> INode.ChildrenAsList
{
get { return _publishedContent.Children.Select(LegacyNodeHelper.ConvertToNode).ToList(); }
}
IProperty INode.GetProperty(string alias)
{
return ((INode)this).PropertiesAsList.Cast<global::umbraco.NodeFactory.Property>().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);
}
}
}

View File

@@ -0,0 +1,54 @@
using System;
using System.Web;
using Umbraco.Core.Models;
using umbraco.interfaces;
namespace Umbraco.Web.Models
{
/// <summary>
/// A legacy IProperty that wraps IPublishedProperty
/// </summary>
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;
}
}
}

View File

@@ -0,0 +1,25 @@
using Umbraco.Core.Models;
using umbraco.interfaces;
namespace Umbraco.Web.Models
{
/// <summary>
/// Used to convert to/from the legacy INode from IPublishedContent
/// </summary>
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);
}
}
}

View File

@@ -268,6 +268,8 @@
</Compile>
<Compile Include="ApplicationContextExtensions.cs" />
<Compile Include="AreaRegistrationContextExtensions.cs" />
<Compile Include="Models\LegacyConvertedNode.cs" />
<Compile Include="Models\LegacyConvertedNodeProperty.cs" />
<Compile Include="Scheduling\BackgroundTaskRunner.cs" />
<Compile Include="BatchedServerMessenger.cs" />
<Compile Include="CacheHelperExtensions.cs" />
@@ -739,7 +741,7 @@
<Compile Include="UI\Bundles\JsUmbracoApplicationUI.cs" />
<Compile Include="UI\Bundles\JsUmbracoTree.cs" />
<Compile Include="UI\CdfLogger.cs" />
<Compile Include="umbraco.presentation\CompatibilityHelper.cs" />
<Compile Include="Models\LegacyNodeHelper.cs" />
<Compile Include="umbraco.presentation\umbraco\controls\PasswordChanger.ascx.cs">
<SubType>ASPXCodeBehind</SubType>
</Compile>

View File

@@ -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<IProperty> PropertiesAsList
{
get { return _doc.Properties.Select(ConvertToNodeProperty).ToList(); }
}
public List<INode> ChildrenAsList
{
get { return _doc.Children.Select(ConvertToNode).ToList(); }
}
public IProperty GetProperty(string alias)
{
return PropertiesAsList.Cast<global::umbraco.NodeFactory.Property>().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;
}
}
}
}

View File

@@ -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

View File

@@ -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;