diff --git a/src/Umbraco.Core/Models/Editors/ContentPropertyData.cs b/src/Umbraco.Core/Models/Editors/ContentPropertyData.cs
new file mode 100644
index 0000000000..98afb691e8
--- /dev/null
+++ b/src/Umbraco.Core/Models/Editors/ContentPropertyData.cs
@@ -0,0 +1,36 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Umbraco.Core.Models.Editors
+{
+ ///
+ /// Represents data that has been submitted to be saved for a content property
+ ///
+ ///
+ /// This object exists because we may need to save additional data for each property, more than just
+ /// the string representation of the value being submitted. An example of this is uploaded files.
+ ///
+ public class ContentPropertyData
+ {
+ public ContentPropertyData(string value, IDictionary additionalData)
+ {
+ Value = value;
+ AdditionalData = new ReadOnlyDictionary(additionalData);
+ }
+
+ ///
+ /// The string value submitted for the property
+ ///
+ public string Value { get; private set; }
+
+ ///
+ /// A dictionary containing any additional objects that are related to this property when saving
+ ///
+ public ReadOnlyDictionary AdditionalData { get; private set; }
+
+ }
+}
diff --git a/src/Umbraco.Core/PropertyEditors/ValueEditor.cs b/src/Umbraco.Core/PropertyEditors/ValueEditor.cs
index 69a5f83a3b..2b8757357f 100644
--- a/src/Umbraco.Core/PropertyEditors/ValueEditor.cs
+++ b/src/Umbraco.Core/PropertyEditors/ValueEditor.cs
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
using Umbraco.Core.Models;
+using Umbraco.Core.Models.Editors;
namespace Umbraco.Core.PropertyEditors
{
@@ -105,6 +106,10 @@ namespace Umbraco.Core.PropertyEditors
/// to an object to be stored in the database.
///
///
+ ///
+ /// The current value that has been persisted to the database for this editor. This value may be usesful for
+ /// how the value then get's deserialized again to be re-persisted. In most cases it will probably not be used.
+ ///
///
///
/// By default this will attempt to automatically convert the string value to the value type supplied by ValueType.
@@ -112,9 +117,9 @@ namespace Umbraco.Core.PropertyEditors
/// If overridden then the object returned must match the type supplied in the ValueType, otherwise persisting the
/// value to the DB will fail when it tries to validate the value type.
///
- public virtual object DeserializeValue(string editorValue)
+ public virtual object DeserializeValue(ContentPropertyData editorValue, object currentValue)
{
- var result = TryConvertValueToCrlType(editorValue);
+ var result = TryConvertValueToCrlType(editorValue.Value);
if (result.Success == false)
{
throw new InvalidOperationException("The value " + editorValue + " cannot be converted to the type " + GetDatabaseType());
diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj
index 1f603f43af..e4f17fdd48 100644
--- a/src/Umbraco.Core/Umbraco.Core.csproj
+++ b/src/Umbraco.Core/Umbraco.Core.csproj
@@ -197,6 +197,7 @@
+
diff --git a/src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/FileUploadPropertyEditor.cs b/src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/FileUploadPropertyEditor.cs
index a1d9a731e4..ca62ca46a0 100644
--- a/src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/FileUploadPropertyEditor.cs
+++ b/src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/FileUploadPropertyEditor.cs
@@ -1,5 +1,4 @@
-using System.Collections.Generic;
-using Umbraco.Core.PropertyEditors;
+using Umbraco.Core.PropertyEditors;
namespace Umbraco.Web.UI.App_Plugins.MyPackage.PropertyEditors
{
@@ -13,16 +12,9 @@ namespace Umbraco.Web.UI.App_Plugins.MyPackage.PropertyEditors
///
protected override ValueEditor CreateValueEditor()
{
- var editor = base.CreateValueEditor();
+ //TODO: Ensure we assign custom validation for uploaded file types!
- editor.Validators = new List { new PostcodeValidator() };
-
- return editor;
+ return new FileUploadValueEditor();
}
}
-
- internal class FileUploadValueEditor : ValueEditor
- {
-
- }
}
\ No newline at end of file
diff --git a/src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/Js/FileUploadEditor.js b/src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/Js/FileUploadEditor.js
index be3f41df08..fc1e73a27d 100644
--- a/src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/Js/FileUploadEditor.js
+++ b/src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/Js/FileUploadEditor.js
@@ -9,7 +9,7 @@ define(['namespaceMgr'], function () {
$scope.$on("fileSelected", function(event, args) {
$scope.$apply(function() {
//assign the file name to the model property
- $scope.model.value = args.file.name;
+ $//scope.model.value = args.file.name;
//save the file object to the scope's files collection
$scope.files.push({ id: $scope.model.id, file: args.file });
});
@@ -17,64 +17,4 @@ define(['namespaceMgr'], function () {
};
-});
-
-function Ctrl($scope, $http) {
-
- //a simple model to bind to and send to the server
- $scope.model = {
- name: "",
- comments: ""
- };
-
- //an array of files selected
- $scope.files = [];
-
- //listen for the file selected event
- $scope.$on("fileSelected", function (event, args) {
- $scope.$apply(function () {
- //add the file object to the scope's files collection
- $scope.files.push(args.file);
- });
- });
-
- //the save method
- $scope.save = function() {
- $http({
- method: 'POST',
- url: "/Api/SaveStuff",
- //IMPORTANT!!! You might think this should be set to 'multipart/form-data'
- // but this is not true because when we are sending up files the request
- // needs to include a 'boundary' parameter which identifies the boundary
- // name between parts in this multi-part request and setting the Content-type
- // manually will not set this boundary parameter. For whatever reason,
- // setting the Content-type to 'false' will force the request to automatically
- // populate the headers properly including the boundary parameter.
- headers: { 'Content-Type': false },
- //This method will allow us to change how the data is sent up to the server
- // for which we'll need to encapsulate the model data in 'FormData'
- transformRequest: function (data) {
- var formData = new FormData();
- //need to convert our json object to a string version of json otherwise
- // the browser will do a 'toString()' on the object which will result
- // in the value '[Object object]' on the server.
- formData.append("model", angular.toJson(data.model));
- //now add all of the assigned files
- for (var i = 0; i < data.files; i++) {
- //add each file to the form data and iteratively name them
- formData.append("file" + i, data.files[i]);
- }
- return formData;
- },
- //Create an object that contains the model and files which will be transformed
- // in the above transformRequest method
- data: { model: $scope.model, files: $scope.files }
- }).
- success(function (data, status, headers, config) {
- alert("success!");
- }).
- error(function (data, status, headers, config) {
- alert("failed!");
- });
- };
-};
\ No newline at end of file
+});
\ No newline at end of file
diff --git a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj
index a88f88ddca..051ff0cf5e 100644
--- a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj
+++ b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj
@@ -286,6 +286,7 @@
+
diff --git a/src/Umbraco.Web/Models/ContentEditing/ContentItemFile.cs b/src/Umbraco.Web/Models/ContentEditing/ContentItemFile.cs
index 5e7a241897..666d6a5553 100644
--- a/src/Umbraco.Web/Models/ContentEditing/ContentItemFile.cs
+++ b/src/Umbraco.Web/Models/ContentEditing/ContentItemFile.cs
@@ -10,9 +10,14 @@
///
public int PropertyId { get; set; }
+ ///
+ /// The original file name
+ ///
+ public string FileName { get; set; }
+
///
/// The file path for the uploaded file for where the MultipartFormDataStreamProvider has saved the temp file
///
- public string FilePath { get; set; }
+ public string TempFilePath { get; set; }
}
}
\ No newline at end of file
diff --git a/src/Umbraco.Web/Models/ContentEditing/ContentPropertyDto.cs b/src/Umbraco.Web/Models/ContentEditing/ContentPropertyDto.cs
index e3f8650689..01b9bc1152 100644
--- a/src/Umbraco.Web/Models/ContentEditing/ContentPropertyDto.cs
+++ b/src/Umbraco.Web/Models/ContentEditing/ContentPropertyDto.cs
@@ -1,5 +1,6 @@
using System.Collections.Generic;
using Umbraco.Core.Models;
+using Umbraco.Core.PropertyEditors;
namespace Umbraco.Web.Models.ContentEditing
{
@@ -11,6 +12,7 @@ namespace Umbraco.Web.Models.ContentEditing
public IDataTypeDefinition DataType { get; set; }
public string Label { get; set; }
public string Alias { get; set; }
- public string Description { get; set; }
+ public string Description { get; set; }
+ public PropertyEditor PropertyEditor { get; set; }
}
}
\ No newline at end of file
diff --git a/src/Umbraco.Web/Models/Mapping/ContentModelMapper.cs b/src/Umbraco.Web/Models/Mapping/ContentModelMapper.cs
index 066e44a4b7..f23c6a2f27 100644
--- a/src/Umbraco.Web/Models/Mapping/ContentModelMapper.cs
+++ b/src/Umbraco.Web/Models/Mapping/ContentModelMapper.cs
@@ -58,7 +58,8 @@ namespace Umbraco.Web.Models.Mapping
Description = p.PropertyType.Description,
Label = p.PropertyType.Name,
Id = p.Id,
- DataType = _applicationContext.Services.DataTypeService.GetDataTypeDefinitionById(p.PropertyType.DataTypeDefinitionId)
+ DataType = _applicationContext.Services.DataTypeService.GetDataTypeDefinitionById(p.PropertyType.DataTypeDefinitionId),
+ PropertyEditor = PropertyEditorResolver.Current.GetById(p.PropertyType.DataTypeId)
}).ToList()
};
}
diff --git a/src/Umbraco.Web/WebApi/ContentEditorApiController.cs b/src/Umbraco.Web/WebApi/ContentEditorApiController.cs
index 7a10e52a38..147bd7b421 100644
--- a/src/Umbraco.Web/WebApi/ContentEditorApiController.cs
+++ b/src/Umbraco.Web/WebApi/ContentEditorApiController.cs
@@ -1,8 +1,12 @@
-using System.Net;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
using System.Net.Http;
using System.Web.Http;
using System.Web.Http.ModelBinding;
using Umbraco.Core;
+using Umbraco.Core.Models.Editors;
+using Umbraco.Core.PropertyEditors;
using Umbraco.Web.Models.ContentEditing;
using Umbraco.Web.Models.Mapping;
using Umbraco.Web.Mvc;
@@ -88,11 +92,22 @@ namespace Umbraco.Web.WebApi
//Save the property values
foreach (var p in contentItem.ContentDto.Properties)
- {
- var prop = contentItem.PersistedContent.Properties[p.Alias];
+ {
+ //get the dbo property
+ var dboProperty = contentItem.PersistedContent.Properties[p.Alias];
- //TODO: We need to get the persistable value from the property editor, not just the posted RAW string value.
- prop.Value = p.Value;
+ //create the property data to send to the property editor
+ var d = new Dictionary();
+ //add the files if any
+ var files = contentItem.UploadedFiles.Where(x => x.PropertyId == p.Id).ToArray();
+ if (files.Any())
+ {
+ d.Add("files", files);
+ }
+ var data = new ContentPropertyData(p.Value, d);
+
+ //get the deserialized value from the property editor
+ dboProperty.Value = p.PropertyEditor.ValueEditor.DeserializeValue(data, dboProperty.Value);
}
//save the item
diff --git a/src/Umbraco.Web/WebApi/ContentItemBinder.cs b/src/Umbraco.Web/WebApi/ContentItemBinder.cs
index f7c50ac9d7..eea8d97ddd 100644
--- a/src/Umbraco.Web/WebApi/ContentItemBinder.cs
+++ b/src/Umbraco.Web/WebApi/ContentItemBinder.cs
@@ -97,6 +97,8 @@ namespace Umbraco.Web.WebApi
//get the files
foreach (var file in result.FileData)
{
+ //The name that has been assigned in JS has 2 parts and the second part indicates the property id
+ // for which the file belongs.
var parts = file.Headers.ContentDisposition.Name.Trim(new char[] { '\"' }).Split('_');
if (parts.Length != 2)
{
@@ -115,10 +117,14 @@ namespace Umbraco.Web.WebApi
ReasonPhrase = "The request was not formatted correctly the file name's 2nd part must be an integer"
});
}
+
+ var fileName = file.Headers.ContentDisposition.FileName.Trim(new char[] {'\"'});
+
model.UploadedFiles.Add(new ContentItemFile
{
- FilePath = file.LocalFileName,
- PropertyId = propertyId
+ TempFilePath = file.LocalFileName,
+ PropertyId = propertyId,
+ FileName = fileName
});
}
diff --git a/src/Umbraco.Web/WebApi/Filters/ContentItemValidationFilterAttribute.cs b/src/Umbraco.Web/WebApi/Filters/ContentItemValidationFilterAttribute.cs
index a61caccdde..1b7dda29fd 100644
--- a/src/Umbraco.Web/WebApi/Filters/ContentItemValidationFilterAttribute.cs
+++ b/src/Umbraco.Web/WebApi/Filters/ContentItemValidationFilterAttribute.cs
@@ -109,7 +109,7 @@ namespace Umbraco.Web.WebApi.Filters
{
foreach (var p in postedItem.ContentDto.Properties)
{
- var editor = PropertyEditorResolver.Current.GetById(p.DataType.ControlId);
+ var editor = p.PropertyEditor;
if (editor == null)
{
var message = string.Format("The property editor with id: {0} was not found for property with id {1}", p.DataType.ControlId, p.Id);
diff --git a/src/Umbraco.Web/WebApi/Filters/FileUploadCleanupFilterAttribute.cs b/src/Umbraco.Web/WebApi/Filters/FileUploadCleanupFilterAttribute.cs
index 4ec28473d8..6b909b9c33 100644
--- a/src/Umbraco.Web/WebApi/Filters/FileUploadCleanupFilterAttribute.cs
+++ b/src/Umbraco.Web/WebApi/Filters/FileUploadCleanupFilterAttribute.cs
@@ -30,7 +30,7 @@ namespace Umbraco.Web.WebApi.Filters
//cleanup any files associated
foreach (var f in contentItem.UploadedFiles)
{
- File.Delete(f.FilePath);
+ File.Delete(f.TempFilePath);
}
}
}