diff --git a/src/Umbraco.Core/Constants-PropertyEditors.cs b/src/Umbraco.Core/Constants-PropertyEditors.cs
index 2f7d247b36..358ca0e5d7 100644
--- a/src/Umbraco.Core/Constants-PropertyEditors.cs
+++ b/src/Umbraco.Core/Constants-PropertyEditors.cs
@@ -419,6 +419,12 @@ namespace Umbraco.Core
/// Alias for the email address property editor
///
public const string EmailAddressAlias = "Umbraco.EmailAddress";
+
+ ///
+ /// Pre-value name used to indicate a field that can be used to override the database field to which data for the associated
+ /// property is saved
+ ///
+ public const string DataValueTypePreValueKey = "umbracoDataValueType";
}
}
}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Models/DataTypeDatabaseType.cs b/src/Umbraco.Core/Models/DataTypeDatabaseType.cs
index 1db8ac65cb..2fccdc0645 100644
--- a/src/Umbraco.Core/Models/DataTypeDatabaseType.cs
+++ b/src/Umbraco.Core/Models/DataTypeDatabaseType.cs
@@ -6,10 +6,6 @@ namespace Umbraco.Core.Models
///
/// Enum of the various DbTypes for which the Property values are stored
///
- ///
- /// Object is added to support complex values from PropertyEditors,
- /// but will be saved under the Ntext column.
- ///
[Serializable]
[DataContract]
public enum DataTypeDatabaseType
diff --git a/src/Umbraco.Core/Models/Property.cs b/src/Umbraco.Core/Models/Property.cs
index d7c2eb92a8..f3fbefda4f 100644
--- a/src/Umbraco.Core/Models/Property.cs
+++ b/src/Umbraco.Core/Models/Property.cs
@@ -124,10 +124,54 @@ namespace Umbraco.Core.Models
bool typeValidation = _propertyType.IsPropertyTypeValid(value);
if (typeValidation == false)
- throw new Exception(
- string.Format(
- "Type validation failed. The value type: '{0}' does not match the DataType in PropertyType with alias: '{1}'",
- value == null ? "null" : value.GetType().Name, Alias));
+ {
+ // Normally we'll throw an exception here. However if the property is of a type that can have it's data field (dataInt, dataVarchar etc.)
+ // changed, we might have a value of the now "wrong" type. As of May 2016 Label is the only built-in property editor that supports this.
+ // In that case we should try to parse the value and return null if that's not possible rather than throwing an exception.
+ if (value != null && _propertyType.CanHaveDataValueTypeChanged())
+ {
+ var stringValue = value.ToString();
+ switch (_propertyType.DataTypeDatabaseType)
+ {
+ case DataTypeDatabaseType.Nvarchar:
+ case DataTypeDatabaseType.Ntext:
+ value = stringValue;
+ break;
+ case DataTypeDatabaseType.Integer:
+ int integerValue;
+ if (int.TryParse(stringValue, out integerValue) == false)
+ {
+ // Edge case, but if changed from decimal --> integer, the above tryparse will fail. So we'll try going
+ // via decimal too to return the integer value rather than zero.
+ decimal decimalForIntegerValue;
+ if (decimal.TryParse(stringValue, out decimalForIntegerValue))
+ {
+ integerValue = (int)decimalForIntegerValue;
+ }
+ }
+
+ value = integerValue;
+ break;
+ case DataTypeDatabaseType.Decimal:
+ decimal decimalValue;
+ decimal.TryParse(stringValue, out decimalValue);
+ value = decimalValue;
+ break;
+ case DataTypeDatabaseType.Date:
+ DateTime dateValue;
+ DateTime.TryParse(stringValue, out dateValue);
+ value = dateValue;
+ break;
+ }
+ }
+ else
+ {
+ throw new Exception(
+ string.Format(
+ "Type validation failed. The value type: '{0}' does not match the DataType in PropertyType with alias: '{1}'",
+ value == null ? "null" : value.GetType().Name, Alias));
+ }
+ }
SetPropertyValueAndDetectChanges(o =>
{
diff --git a/src/Umbraco.Core/Models/PropertyType.cs b/src/Umbraco.Core/Models/PropertyType.cs
index 0649801a0c..00e7fc8d13 100644
--- a/src/Umbraco.Core/Models/PropertyType.cs
+++ b/src/Umbraco.Core/Models/PropertyType.cs
@@ -1,5 +1,6 @@
using System;
using System.Diagnostics;
+using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;
using System.Text.RegularExpressions;
@@ -425,6 +426,19 @@ namespace Umbraco.Core.Models
return false;
}
+ ///
+ /// Checks the underlying property editor prevalues to see if the one that allows changing of the database field
+ /// to which data is saved (dataInt, dataVarchar etc.) is included. If so that means the field could be changed when the data
+ /// type is saved.
+ ///
+ ///
+ internal bool CanHaveDataValueTypeChanged()
+ {
+ var propertyEditor = PropertyEditorResolver.Current.GetByAlias(_propertyEditorAlias);
+ return propertyEditor.PreValueEditor.Fields
+ .SingleOrDefault(x => x.Key == Constants.PropertyEditors.DataValueTypePreValueKey) != null;
+ }
+
///
/// Validates the Value from a Property according to the validation settings
///
diff --git a/src/Umbraco.Core/PropertyEditors/PropertyValueEditor.cs b/src/Umbraco.Core/PropertyEditors/PropertyValueEditor.cs
index eb08b07d43..a7154d7d67 100644
--- a/src/Umbraco.Core/PropertyEditors/PropertyValueEditor.cs
+++ b/src/Umbraco.Core/PropertyEditors/PropertyValueEditor.cs
@@ -130,20 +130,20 @@ namespace Umbraco.Core.PropertyEditors
{
switch (ValueType.ToUpper(CultureInfo.InvariantCulture))
{
- case "INT":
- case "INTEGER":
+ case PropertyEditorValueTypes.IntegerType:
+ case PropertyEditorValueTypes.IntegerTypeAlternative:
return DataTypeDatabaseType.Integer;
- case "DECIMAL":
+ case PropertyEditorValueTypes.DecimalType:
return DataTypeDatabaseType.Decimal;
- case "STRING":
+ case PropertyEditorValueTypes.StringType:
return DataTypeDatabaseType.Nvarchar;
- case "TEXT":
- case "JSON":
- case "XML":
+ case PropertyEditorValueTypes.TextType:
+ case PropertyEditorValueTypes.JsonType:
+ case PropertyEditorValueTypes.XmlType:
return DataTypeDatabaseType.Ntext;
- case "DATETIME":
- case "DATE":
- case "TIME":
+ case PropertyEditorValueTypes.DateTimeType:
+ case PropertyEditorValueTypes.DateType:
+ case PropertyEditorValueTypes.TimeType:
return DataTypeDatabaseType.Date;
default:
throw new FormatException("The ValueType does not match a known value type");
diff --git a/src/Umbraco.Core/Services/DataTypeService.cs b/src/Umbraco.Core/Services/DataTypeService.cs
index 035cfd0ab6..75234fa3ab 100644
--- a/src/Umbraco.Core/Services/DataTypeService.cs
+++ b/src/Umbraco.Core/Services/DataTypeService.cs
@@ -504,6 +504,8 @@ namespace Umbraco.Core.Services
if (Saving.IsRaisedEventCancelled(new SaveEventArgs(dataTypeDefinition), this))
return;
+ OverrideDatabaseTypeIfProvidedInPreValues(dataTypeDefinition, values);
+
var uow = UowProvider.GetUnitOfWork();
using (var repository = RepositoryFactory.CreateDataTypeDefinitionRepository(uow))
{
@@ -523,6 +525,36 @@ namespace Umbraco.Core.Services
Audit(AuditType.Save, string.Format("Save DataTypeDefinition performed by user"), userId, dataTypeDefinition.Id);
}
+ ///
+ /// If the database data field is provided in the pre-values update the data type definition to that instead of the
+ /// default for the property editor
+ ///
+ ///
+ ///
+ private static void OverrideDatabaseTypeIfProvidedInPreValues(IDataTypeDefinition dataTypeDefinition, IDictionary values)
+ {
+ if (values != null && values.ContainsKey(Constants.PropertyEditors.DataValueTypePreValueKey))
+ {
+ switch (values[Constants.PropertyEditors.DataValueTypePreValueKey].Value)
+ {
+ case PropertyEditorValueTypes.StringType:
+ dataTypeDefinition.DatabaseType = DataTypeDatabaseType.Nvarchar;
+ break;
+ case PropertyEditorValueTypes.IntegerType:
+ dataTypeDefinition.DatabaseType = DataTypeDatabaseType.Integer;
+ break;
+ case PropertyEditorValueTypes.DecimalType:
+ dataTypeDefinition.DatabaseType = DataTypeDatabaseType.Decimal;
+ break;
+ case PropertyEditorValueTypes.DateTimeType:
+ dataTypeDefinition.DatabaseType = DataTypeDatabaseType.Date;
+ break;
+ case PropertyEditorValueTypes.TextType:
+ dataTypeDefinition.DatabaseType = DataTypeDatabaseType.Ntext;
+ break;
+ }
+ }
+ }
///
/// Deletes an
diff --git a/src/Umbraco.Web/PropertyEditors/LabelPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/LabelPropertyEditor.cs
index 1132fcfacd..fab9d0bba3 100644
--- a/src/Umbraco.Web/PropertyEditors/LabelPropertyEditor.cs
+++ b/src/Umbraco.Web/PropertyEditors/LabelPropertyEditor.cs
@@ -41,7 +41,6 @@ namespace Umbraco.Web.PropertyEditors
internal class LabelPreValueEditor : PreValueEditor
{
- private const string ValueTypeKey = "valueType";
private const string LegacyPropertyEditorValuesKey = "values";
public LabelPreValueEditor()
@@ -56,7 +55,7 @@ namespace Umbraco.Web.PropertyEditors
ValueType = PropertyEditorValueTypes.StringType;
}
- [PreValueField(ValueTypeKey, "Value type", "valuetype")]
+ [PreValueField(Constants.PropertyEditors.DataValueTypePreValueKey, "Value type", "valuetype")]
public string ValueType { get; set; }
///
@@ -72,19 +71,19 @@ namespace Umbraco.Web.PropertyEditors
// Check for a saved value type. If not found set to default string type.
var valueType = PropertyEditorValueTypes.StringType;
- if (existing.ContainsKey(ValueTypeKey))
+ if (existing.ContainsKey(Constants.PropertyEditors.DataValueTypePreValueKey))
{
- valueType = (string)existing[ValueTypeKey];
+ valueType = (string)existing[Constants.PropertyEditors.DataValueTypePreValueKey];
}
// Convert any other values from a legacy property editor to a list, easier to enumerate on the editor.
// Make sure to exclude values defined on the label property editor itself.
var asList = existing
.Select(e => new KeyValuePair(e.Key, e.Value))
- .Where(e => e.Key != ValueTypeKey)
+ .Where(e => e.Key != Constants.PropertyEditors.DataValueTypePreValueKey)
.ToList();
- var result = new Dictionary { { ValueTypeKey, valueType } };
+ var result = new Dictionary { { Constants.PropertyEditors.DataValueTypePreValueKey, valueType } };
if (asList.Any())
{
result.Add("values", asList);