diff --git a/default.build b/default.build
index 6be7ce3532..647559ec61 100644
--- a/default.build
+++ b/default.build
@@ -14,7 +14,11 @@
+
+
+
+
@@ -41,8 +45,7 @@
-
-
+
@@ -68,7 +71,26 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -77,16 +99,53 @@
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -108,13 +167,15 @@
+
+
@@ -133,13 +194,14 @@
+
-
+
@@ -232,35 +294,7 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
@@ -329,7 +363,7 @@
-
+
@@ -339,7 +373,7 @@
-
+
@@ -348,15 +382,34 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
diff --git a/umbraco.MacroEngines.Juno/RazorDynamicNode/DynamicNode.cs b/umbraco.MacroEngines.Juno/RazorDynamicNode/DynamicNode.cs
index e2b22078d6..55e60d2a28 100644
--- a/umbraco.MacroEngines.Juno/RazorDynamicNode/DynamicNode.cs
+++ b/umbraco.MacroEngines.Juno/RazorDynamicNode/DynamicNode.cs
@@ -205,20 +205,21 @@ namespace umbraco.MacroEngines
{
var name = binder.Name;
+ result = null; //this will never be returned
if (name == "ChildrenAsList" || name == "Children")
{
result = GetChildrenAsList;
return true;
}
-
+ bool propertyExists = false;
if (n != null)
{
- var data = n.GetProperty(name);
+ var data = n.GetProperty(name, out propertyExists);
// check for nicer support of Pascal Casing EVEN if alias is camelCasing:
- if (data == null && name.Substring(0, 1).ToUpper() == name.Substring(0, 1))
+ if (data == null && name.Substring(0, 1).ToUpper() == name.Substring(0, 1) && !propertyExists)
{
- data = n.GetProperty(name.Substring(0, 1).ToLower() + name.Substring((1)));
+ data = n.GetProperty(name.Substring(0, 1).ToLower() + name.Substring((1)), out propertyExists);
}
if (data != null)
@@ -265,10 +266,17 @@ namespace umbraco.MacroEngines
//if property access, type lookup and member invoke all failed
//at this point, we're going to return null
- //instead, we return an empty list
+ //instead, we return a DynamicNull - see comments in that file
//this will let things like Model.ChildItem work and return nothing instead of crashing
- result = new DynamicNodeList(new List());
- //changed this to a return true because it breaks testing when using .Children().Random().propertyName
+ if (!propertyExists && result == null)
+ {
+ //.Where explictly checks for this type
+ //and will make it false
+ //which means backwards equality (&& property != true) will pass
+ //forwwards equality (&& property or && property == true) will fail
+ result = new DynamicNull();
+ return true;
+ }
return true;
}
@@ -281,7 +289,7 @@ namespace umbraco.MacroEngines
if (dataType == DATATYPE_YESNO_GUID)
{
bool parseResult;
- if (result.ToString() == "") result = "0";
+ if (string.Format("{0}", result) == "") result = "0";
if (Boolean.TryParse(result.ToString().Replace("1", "true").Replace("0", "false"), out parseResult))
{
result = parseResult;
diff --git a/umbraco.MacroEngines.Juno/RazorDynamicNode/DynamicNull.cs b/umbraco.MacroEngines.Juno/RazorDynamicNode/DynamicNull.cs
new file mode 100644
index 0000000000..7bfe6462c5
--- /dev/null
+++ b/umbraco.MacroEngines.Juno/RazorDynamicNode/DynamicNull.cs
@@ -0,0 +1,34 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Collections;
+using System.Dynamic;
+
+namespace umbraco.MacroEngines
+{
+ //This type is used as a return type when TryGetMember fails on a DynamicNode
+ //.Where explicitly checks for this type, to indicate that nothing was returned
+ //Because it's IEnumerable, if the user is actually trying @Model.TextPages or similar
+ //it will still return an enumerable object (assuming the call actually failed because there were no children of that type)
+ //but in .Where, if they use a property that doesn't exist, the lambda will bypass this and return false
+ public class DynamicNull : DynamicObject, IEnumerable
+ {
+ public IEnumerator GetEnumerator()
+ {
+ return (new List()).GetEnumerator();
+ }
+ public DynamicNull Where(string predicate, params object[] values)
+ {
+ return this;
+ }
+ public DynamicNull OrderBy(string orderBy)
+ {
+ return this;
+ }
+ public override string ToString()
+ {
+ return string.Empty;
+ }
+ }
+}
diff --git a/umbraco.MacroEngines.Juno/RazorDynamicNode/DynamicQueryable.cs b/umbraco.MacroEngines.Juno/RazorDynamicNode/DynamicQueryable.cs
index 6d8202c3b5..1f1833869c 100644
--- a/umbraco.MacroEngines.Juno/RazorDynamicNode/DynamicQueryable.cs
+++ b/umbraco.MacroEngines.Juno/RazorDynamicNode/DynamicQueryable.cs
@@ -54,6 +54,7 @@ namespace System.Linq.Dynamic
{
return (bool)value;
}
+
return false;
}
catch (Exception)
@@ -1467,6 +1468,12 @@ namespace System.Linq.Dynamic
Expression.Assign(result, Expression.Constant(null)),
Expression.IfThen(Expression.NotEqual(Expression.Constant(null), instanceExpression),
Expression.Call(instanceExpression, method, binder, result)),
+ Expression.IfThen(
+ Expression.TypeEqual(result, typeof(DynamicNull)),
+ Expression.Assign(result,
+ Expression.Constant(false, typeof(object))
+ )
+ ),
Expression.Return(blockReturnLabel, result),
Expression.Label(blockReturnLabel, Expression.Constant(-2, typeof(object)))
);
diff --git a/umbraco.MacroEngines.Juno/umbraco.MacroEngines.csproj b/umbraco.MacroEngines.Juno/umbraco.MacroEngines.csproj
index 9fef26f020..286cde54dc 100644
--- a/umbraco.MacroEngines.Juno/umbraco.MacroEngines.csproj
+++ b/umbraco.MacroEngines.Juno/umbraco.MacroEngines.csproj
@@ -64,6 +64,7 @@
+
diff --git a/umbraco.sln b/umbraco.sln
index 0f4e59c558..f41144e7b7 100644
--- a/umbraco.sln
+++ b/umbraco.sln
@@ -22,7 +22,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "StandardConfig", "StandardC
config templates\umbraco.config = config templates\umbraco.config
config templates\config\umbracoSettings.config = config templates\config\umbracoSettings.config
config templates\config\UrlRewriting.config = config templates\config\UrlRewriting.config
- config templates\web.config = config templates\web.config
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Packages", "Packages", "{5BB61485-B480-4A03-A8DD-1636A5AF575C}"
diff --git a/umbraco/interfaces/INode.cs b/umbraco/interfaces/INode.cs
index d3c9ca1bd8..e4ecd9c215 100644
--- a/umbraco/interfaces/INode.cs
+++ b/umbraco/interfaces/INode.cs
@@ -29,6 +29,7 @@ namespace umbraco.interfaces
List PropertiesAsList { get; }
List ChildrenAsList { get; }
IProperty GetProperty(string Alias);
+ IProperty GetProperty(string Alias, out bool propertyExists);
DataTable ChildrenAsTable();
DataTable ChildrenAsTable(string nodeTypeAliasFilter);
}
diff --git a/umbraco/presentation/umbraco.presentation.csproj b/umbraco/presentation/umbraco.presentation.csproj
index 94738f3954..775b903e97 100644
--- a/umbraco/presentation/umbraco.presentation.csproj
+++ b/umbraco/presentation/umbraco.presentation.csproj
@@ -1922,6 +1922,7 @@
+
Designer
diff --git a/umbraco/presentation/umbraco/create/DLRScripting.ascx.cs b/umbraco/presentation/umbraco/create/DLRScripting.ascx.cs
index 4c4983619d..3c55f39b9f 100644
--- a/umbraco/presentation/umbraco/create/DLRScripting.ascx.cs
+++ b/umbraco/presentation/umbraco/create/DLRScripting.ascx.cs
@@ -61,6 +61,9 @@ namespace umbraco.presentation.create
string abPath = IO.IOHelper.MapPath(path);
list.Items.Clear();
+ // always add the option of an empty one
+ list.Items.Add(new ListItem("Empty template", ""));
+
if (System.IO.Directory.Exists(abPath))
{
string extension = "." + scriptType;
@@ -72,10 +75,6 @@ namespace umbraco.presentation.create
list.Items.Add(new ListItem(helper.SpaceCamelCasing(filename.Replace(extension, "")), scriptType + "/" + filename));
}
}
- else
- {
- list.Items.Add(new ListItem("Empty template", ""));
- }
}
}
}
\ No newline at end of file
diff --git a/umbraco/presentation/umbraco/nodeFactory/Page.cs b/umbraco/presentation/umbraco/nodeFactory/Page.cs
index a182c6a4b8..a554472f30 100644
--- a/umbraco/presentation/umbraco/nodeFactory/Page.cs
+++ b/umbraco/presentation/umbraco/nodeFactory/Page.cs
@@ -314,6 +314,20 @@ namespace umbraco.NodeFactory
return null;
}
+ public IProperty GetProperty(string Alias, out bool propertyExists)
+ {
+ foreach (Property p in Properties)
+ {
+ if (p.Alias == Alias)
+ {
+ propertyExists = true;
+ return p;
+ }
+ }
+ propertyExists = false;
+ return null;
+ }
+
public static Node GetNodeByXpath(string xpath)
{
XPathNodeIterator xpathNode = library.GetXmlNodeByXPath(xpath);
diff --git a/umbraco/presentation/web.config b/umbraco/presentation/web.config
index 6d8e33b4d3..1308072404 100644
--- a/umbraco/presentation/web.config
+++ b/umbraco/presentation/web.config
@@ -39,8 +39,8 @@
-
-
+
+
diff --git a/umbraco/presentation/web.config.ssaolap01.xslt b/umbraco/presentation/web.config.ssaolap01.xslt
index 98e733067d..dc347ada6e 100644
--- a/umbraco/presentation/web.config.ssaolap01.xslt
+++ b/umbraco/presentation/web.config.ssaolap01.xslt
@@ -8,7 +8,7 @@
- 4.6.1
+ 4.7.0.beta