Hugely simplifies setting properties from macro parameters on user control macros with tests.
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Web.Caching;
|
||||
using System.Web.UI;
|
||||
using System.Web.UI.WebControls;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Profiling;
|
||||
@@ -34,6 +36,40 @@ namespace Umbraco.Tests.Macros
|
||||
ApplicationContext.Current = null;
|
||||
}
|
||||
|
||||
[TestCase("123", "IntProp", typeof(int))]
|
||||
[TestCase("Hello", "StringProp", typeof(string))]
|
||||
[TestCase("123456789.01", "DoubleProp", typeof(double))]
|
||||
[TestCase("1234567", "FloatProp", typeof(float))]
|
||||
[TestCase("1", "BoolProp", typeof(bool))]
|
||||
[TestCase("true", "BoolProp", typeof(bool))]
|
||||
[TestCase("0", "BoolProp", typeof(bool))]
|
||||
[TestCase("false", "BoolProp", typeof(bool))]
|
||||
[TestCase("2001-05-10", "DateProp", typeof(DateTime))]
|
||||
[TestCase("123px", "UnitProp", typeof(Unit))]
|
||||
[TestCase("456pt", "UnitProp", typeof(Unit))]
|
||||
[TestCase("CEC063D3-D73E-4B7D-93ED-7F69CA9BF2D0", "GuidProp", typeof(Guid))]
|
||||
[TestCase("CEC063D3D73E4B7D93ED7F69CA9BF2D0", "GuidProp", typeof(Guid))]
|
||||
[TestCase("", "NullDateProp", typeof(DateTime?))]
|
||||
[TestCase("2001-05-10", "NullDateProp", typeof(DateTime?))]
|
||||
[TestCase("", "NullUnitProp", typeof(Unit?))]
|
||||
[TestCase("456pt", "NullUnitProp", typeof(Unit?))]
|
||||
public void SetUserControlProperty(string val, string macroPropName, Type convertTo)
|
||||
{
|
||||
var ctrl = new UserControlTest();
|
||||
var macroModel = new MacroModel("test", "test", "", "~/usercontrols/menu.ascx", "", "", 0, false, false);
|
||||
macroModel.Properties.Add(new MacroPropertyModel(macroPropName, val));
|
||||
|
||||
macro.UpdateControlProperties(ctrl, macroModel);
|
||||
|
||||
var ctrlType = ctrl.GetType();
|
||||
var prop = ctrlType.GetProperty(macroPropName);
|
||||
var converted = val.TryConvertTo(convertTo);
|
||||
|
||||
Assert.IsTrue(converted.Success);
|
||||
Assert.NotNull(prop);
|
||||
Assert.AreEqual(converted.Result, prop.GetValue(ctrl, null));
|
||||
}
|
||||
|
||||
[TestCase("text.xslt", "", "", "", "XSLT")]
|
||||
[TestCase("", "razor-script.cshtml", "", "", "Script")]
|
||||
[TestCase("", "~/Views/MacroPartials/test.cshtml", "", "", "PartialView")]
|
||||
@@ -116,5 +152,18 @@ namespace Umbraco.Tests.Macros
|
||||
//var asdf = macro.GetCacheIdentifier()
|
||||
}
|
||||
|
||||
private class UserControlTest : UserControl
|
||||
{
|
||||
public int IntProp { get; set; }
|
||||
public string StringProp { get; set; }
|
||||
public double DoubleProp { get; set; }
|
||||
public float FloatProp { get; set; }
|
||||
public bool BoolProp { get; set; }
|
||||
public DateTime DateProp { get; set; }
|
||||
public Unit UnitProp { get; set; }
|
||||
public Guid GuidProp { get; set; }
|
||||
public DateTime? NullDateProp { get; set; }
|
||||
public Unit? NullUnitProp { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Web.UI.WebControls;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Tests.PartialTrust;
|
||||
@@ -19,6 +20,20 @@ namespace Umbraco.Tests
|
||||
TestHelper.SetupLog4NetForTests();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CanParseStringToUnit()
|
||||
{
|
||||
var stringUnit = "1234px";
|
||||
object objUnit = "1234px";
|
||||
var result = stringUnit.TryConvertTo<Unit>();
|
||||
var result2 = objUnit.TryConvertTo<Unit>();
|
||||
var unit = new Unit("1234px");
|
||||
Assert.IsTrue(result.Success);
|
||||
Assert.IsTrue(result2.Success);
|
||||
Assert.AreEqual(unit, result.Result);
|
||||
Assert.AreEqual(unit, result2.Result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Convert_List_To_Enumerable()
|
||||
{
|
||||
|
||||
@@ -1595,156 +1595,55 @@ namespace umbraco
|
||||
return new LiteralControl(string.Format("Unable to create control {0} from assembly {1}",
|
||||
controlName, asm.FullName));
|
||||
|
||||
AddCurrentNodeToControl(control, type);
|
||||
AddCurrentNodeToControl(control);
|
||||
|
||||
// Properties
|
||||
UpdateControlProperties(type, control, model);
|
||||
UpdateControlProperties(control, model);
|
||||
return control;
|
||||
}
|
||||
|
||||
private static void UpdateControlProperties(Type type, Control control, MacroModel model)
|
||||
//TODO: SD : We *really* need to get macro's rendering properly with a real macro engine
|
||||
// and move logic like this (after it is completely overhauled) to a UserControlMacroEngine.
|
||||
internal static void UpdateControlProperties(Control control, MacroModel model)
|
||||
{
|
||||
foreach (MacroPropertyModel mp in model.Properties)
|
||||
var type = control.GetType();
|
||||
|
||||
foreach (var mp in model.Properties)
|
||||
{
|
||||
PropertyInfo prop = type.GetProperty(mp.Key);
|
||||
var prop = type.GetProperty(mp.Key);
|
||||
if (prop == null)
|
||||
{
|
||||
TraceWarn("macro", string.Format("control property '{0}' doesn't exist or aren't accessible (public)", mp.Key));
|
||||
continue;
|
||||
}
|
||||
|
||||
object propValue = mp.Value;
|
||||
bool propValueSet = false;
|
||||
// Special case for types of webControls.unit
|
||||
if (prop.PropertyType == typeof(Unit))
|
||||
{
|
||||
propValue = Unit.Parse(propValue.ToString());
|
||||
propValueSet = true;
|
||||
}
|
||||
else
|
||||
var tryConvert = mp.Value.TryConvertTo(prop.PropertyType);
|
||||
if (tryConvert.Success)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (mp.CLRType == null)
|
||||
continue;
|
||||
var st = (TypeCode)Enum.Parse(typeof(TypeCode), mp.CLRType, true);
|
||||
|
||||
// Special case for booleans
|
||||
if (prop.PropertyType == typeof(bool))
|
||||
{
|
||||
bool parseResult;
|
||||
if (
|
||||
Boolean.TryParse(
|
||||
propValue.ToString().Replace("1", "true").Replace("0", "false"),
|
||||
out parseResult))
|
||||
propValue = parseResult;
|
||||
else
|
||||
propValue = false;
|
||||
propValueSet = true;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
string sPropValue = string.Format("{0}", propValue);
|
||||
Type propType = prop.PropertyType;
|
||||
if (!string.IsNullOrWhiteSpace(sPropValue))
|
||||
{
|
||||
try
|
||||
{
|
||||
propValue = Convert.ChangeType(propValue, st);
|
||||
propValueSet = true;
|
||||
}
|
||||
catch (FormatException)
|
||||
{
|
||||
propValue = Convert.ChangeType(propValue, propType);
|
||||
propValueSet = true;
|
||||
}
|
||||
}
|
||||
/* NH 06-01-2012: Remove the lines below as they would only get activated if the values are empty
|
||||
else
|
||||
{
|
||||
if (propType != null)
|
||||
{
|
||||
if (propType.IsValueType)
|
||||
{
|
||||
propValue = Activator.CreateInstance(propType);
|
||||
}
|
||||
else
|
||||
{
|
||||
propValue = null;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
if (GlobalSettings.DebugMode)
|
||||
TraceInfo("macro.loadControlProperties",
|
||||
string.Format("Property added '{0}' with value '{1}'",
|
||||
mp.Key,
|
||||
propValue));
|
||||
prop.SetValue(control, tryConvert.Result, null);
|
||||
}
|
||||
catch (Exception PropException)
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.WarnWithException<macro>(string.Format(
|
||||
"Error adding property '{0}' with value '{1}'",
|
||||
mp.Key, propValue), PropException);
|
||||
LogHelper.WarnWithException<macro>(string.Format("Error adding property '{0}' with value '{1}'", mp.Key, mp.Value), ex);
|
||||
if (GlobalSettings.DebugMode)
|
||||
{
|
||||
TraceWarn("macro.loadControlProperties", string.Format("Error adding property '{0}' with value '{1}'", mp.Key, mp.Value), ex);
|
||||
}
|
||||
}
|
||||
|
||||
if (GlobalSettings.DebugMode)
|
||||
{
|
||||
TraceWarn("macro.loadControlProperties",
|
||||
string.Format(
|
||||
"Error adding property '{0}' with value '{1}'",
|
||||
mp.Key, propValue), PropException);
|
||||
}
|
||||
if (GlobalSettings.DebugMode)
|
||||
{
|
||||
TraceInfo("macro.UpdateControlProperties", string.Format("Property added '{0}' with value '{1}'", mp.Key, mp.Value));
|
||||
}
|
||||
}
|
||||
|
||||
// NH 06-01-2012: Only set value if it has content
|
||||
if (propValueSet)
|
||||
else
|
||||
{
|
||||
//GE 06-05-2012: Handle Nullable<T> properties
|
||||
if (prop.PropertyType.IsGenericType && prop.PropertyType.Name == "Nullable`1")
|
||||
LogHelper.Warn<macro>(string.Format("Error adding property '{0}' with value '{1}'", mp.Key, mp.Value));
|
||||
if (GlobalSettings.DebugMode)
|
||||
{
|
||||
Type underlyingType = Nullable.GetUnderlyingType(prop.PropertyType);
|
||||
if (underlyingType != null)
|
||||
{
|
||||
object safeValue = null;
|
||||
if (propValue != null)
|
||||
{
|
||||
if (!(underlyingType == typeof(Guid)))
|
||||
{
|
||||
prop.SetValue(control, Convert.ChangeType(propValue, underlyingType), null);
|
||||
}
|
||||
else
|
||||
{
|
||||
Guid g = Guid.Empty;
|
||||
if (Guid.TryParse(string.Format("{0}", propValue), out g))
|
||||
{
|
||||
prop.SetValue(control, g, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
prop.SetValue(control, safeValue, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//GE 06-05-2012: Handle Guid properties as Convert.ChangeType throws on string->Guid
|
||||
if (!(prop.PropertyType == typeof(Guid)))
|
||||
{
|
||||
prop.SetValue(control, Convert.ChangeType(propValue, prop.PropertyType), null);
|
||||
}
|
||||
else
|
||||
{
|
||||
Guid g = Guid.Empty;
|
||||
if (Guid.TryParse(string.Format("{0}", propValue), out g))
|
||||
{
|
||||
prop.SetValue(control, g, null);
|
||||
}
|
||||
}
|
||||
TraceWarn("macro.loadControlProperties", string.Format("Error adding property '{0}' with value '{1}'", mp.Key, mp.Value));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1784,10 +1683,8 @@ namespace umbraco
|
||||
|
||||
TraceInfo(LoadUserControlKey, string.Format("Usercontrol added with id '{0}'", oControl.ID));
|
||||
|
||||
Type type = oControl.GetType();
|
||||
|
||||
AddCurrentNodeToControl(oControl, type);
|
||||
UpdateControlProperties(type, oControl, model);
|
||||
AddCurrentNodeToControl(oControl);
|
||||
UpdateControlProperties(oControl, model);
|
||||
return oControl;
|
||||
}
|
||||
catch (Exception e)
|
||||
@@ -1797,8 +1694,10 @@ namespace umbraco
|
||||
}
|
||||
}
|
||||
|
||||
private static void AddCurrentNodeToControl(Control control, Type type)
|
||||
private static void AddCurrentNodeToControl(Control control)
|
||||
{
|
||||
var type = control.GetType();
|
||||
|
||||
PropertyInfo currentNodeProperty = type.GetProperty("CurrentNode");
|
||||
if (currentNodeProperty != null && currentNodeProperty.CanWrite &&
|
||||
currentNodeProperty.PropertyType.IsAssignableFrom(typeof(Node)))
|
||||
|
||||
@@ -8,7 +8,10 @@ namespace umbraco.cms.businesslogic.macro
|
||||
public string Key { get; set; }
|
||||
public string Value { get; set; }
|
||||
public string Type { get; set; }
|
||||
public string CLRType { get; set; }
|
||||
|
||||
[Obsolete("This is no longer used an will be removed in future versions")]
|
||||
public string CLRType { get; set; }
|
||||
|
||||
public MacroPropertyModel()
|
||||
{
|
||||
|
||||
|
||||
Reference in New Issue
Block a user