Hugely simplifies setting properties from macro parameters on user control macros with tests.

This commit is contained in:
Shannon
2013-11-11 12:22:29 +11:00
parent d76336cd39
commit a311a54d3d
4 changed files with 99 additions and 133 deletions

View File

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

View File

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

View File

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

View File

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