diff --git a/src/Umbraco.Web.UI.Client/src/common/services/menuactions.service.js b/src/Umbraco.Web.UI.Client/src/common/services/menuactions.service.js
index 302834194c..583678b86f 100644
--- a/src/Umbraco.Web.UI.Client/src/common/services/menuactions.service.js
+++ b/src/Umbraco.Web.UI.Client/src/common/services/menuactions.service.js
@@ -14,7 +14,7 @@ function umbracoMenuActions($q, treeService, $location) {
/**
* @ngdoc method
- * @name umbraco.services.umbracoMenuActions#RefreshNodeMenuItem
+ * @name umbraco.services.umbracoMenuActions#RefreshNode
* @methodOf umbraco.services.umbracoMenuActions
* @function
*
@@ -24,7 +24,7 @@ function umbracoMenuActions($q, treeService, $location) {
* @param {object} args.treeNode The tree node
* @param {object} args.section The current section
*/
- "RefreshNodeMenuItem": function (args) {
+ "RefreshNode": function (args) {
treeService.loadNodeChildren({ node: args.treeNode, section: args.section });
},
diff --git a/src/Umbraco.Web.UI.Client/src/views/datatype/datatype.edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/datatype/datatype.edit.controller.js
index 72e52d835c..a6ac7b319e 100644
--- a/src/Umbraco.Web.UI.Client/src/views/datatype/datatype.edit.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/datatype/datatype.edit.controller.js
@@ -108,10 +108,7 @@ function DataTypeEditController($scope, $routeParams, $location, dataTypeResourc
contentEditingHelper.handleSaveError({
err: err,
allNewProps: $scope.preValues,
- allOrigProps: $scope.preValues,
- rebindCallback: function () {
- createPreValueProps(err.data.preValues);
- }
+ allOrigProps: $scope.preValues
});
});
};
diff --git a/src/Umbraco.Web/Editors/DataTypeController.cs b/src/Umbraco.Web/Editors/DataTypeController.cs
index 91ff59eecd..ba66776276 100644
--- a/src/Umbraco.Web/Editors/DataTypeController.cs
+++ b/src/Umbraco.Web/Editors/DataTypeController.cs
@@ -2,7 +2,6 @@
using System.Collections.Generic;
using System.Linq;
using System.Net;
-using System.Net.Http;
using System.Web.Http;
using System.Web.Http.ModelBinding;
using AutoMapper;
@@ -68,79 +67,17 @@ namespace Umbraco.Web.Editors
///
///
///
+ [DataTypeValidate]
public DataTypeDisplay PostSave(DataTypeSave dataType)
{
- //Validate that the property editor exists
- var propertyEditor = PropertyEditorResolver.Current.GetById(dataType.SelectedEditor);
- if (propertyEditor == null)
- {
- var message = string.Format("Property editor with id: {0} was not found", dataType.SelectedEditor);
- throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.NotFound, message));
- }
-
- //Validate the data type exists or create one if required
- IDataTypeDefinition persisted;
- switch (dataType.Action)
- {
- case ContentSaveAction.Save:
- persisted = ApplicationContext.Services.DataTypeService.GetDataTypeDefinitionById(dataType.Id);
- if (persisted == null)
- {
- var message = string.Format("Data type with id: {0} was not found", dataType.Id);
- throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.NotFound, message));
- }
- //map the model to the persisted instance
- Mapper.Map(dataType, persisted);
- break;
- case ContentSaveAction.SaveNew:
- //create the persisted model from mapping the saved model
- persisted = Mapper.Map(dataType);
- break;
- default:
- throw new HttpResponseException(HttpStatusCode.NotFound);
- }
-
- //Validate each field
- foreach (var preVal in dataType.PreValues)
- {
- var postedValue = preVal.Value;
-
- foreach (var v in propertyEditor.PreValueEditor.Fields.SelectMany(x => x.Validators))
- {
- foreach (var result in v.Validate(postedValue, preVal.Key, propertyEditor))
- {
- //if there are no member names supplied then we assume that the validation message is for the overall property
- // not a sub field on the property editor
- if (!result.MemberNames.Any())
- {
- //add a model state error for the entire property
- ModelState.AddModelError(string.Format("{0}.{1}", "Properties", preVal.Key), result.ErrorMessage);
- }
- else
- {
- //there's assigned field names so we'll combine the field name with the property name
- // so that we can try to match it up to a real sub field of this editor
- foreach (var field in result.MemberNames)
- {
- ModelState.AddModelError(string.Format("{0}.{1}.{2}", "Properties", preVal.Key, field), result.ErrorMessage);
- }
- }
- }
- }
- }
-
- if (ModelState.IsValid == false)
- {
- //if it is not valid, do not continue and return the model state
- throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.Forbidden, ModelState));
- }
+ //If we've made it here, then everything has been wired up and validated by the attribute
//finally we need to save the data type and it's pre-vals
var dtService = (DataTypeService) ApplicationContext.Services.DataTypeService;
var preVals = Mapper.Map(dataType.PreValues);
- dtService.SaveDataTypeAndPreValues(persisted, preVals, (int)Security.CurrentUser.Id);
+ dtService.SaveDataTypeAndPreValues(dataType.PersistedDataType, preVals, (int)Security.CurrentUser.Id);
- var display = Mapper.Map(persisted);
+ var display = Mapper.Map(dataType.PersistedDataType);
display.AddSuccessNotification(ui.Text("speechBubbles", "dataTypeSaved"), "");
//now return the updated model
diff --git a/src/Umbraco.Web/Editors/DataTypeValidateAttribute.cs b/src/Umbraco.Web/Editors/DataTypeValidateAttribute.cs
new file mode 100644
index 0000000000..07b839eabe
--- /dev/null
+++ b/src/Umbraco.Web/Editors/DataTypeValidateAttribute.cs
@@ -0,0 +1,119 @@
+using System;
+using System.Linq;
+using System.Net;
+using System.Net.Http;
+using System.Web.Http;
+using System.Web.Http.Controllers;
+using System.Web.Http.Filters;
+using AutoMapper;
+using Umbraco.Core;
+using Umbraco.Core.Models;
+using Umbraco.Core.PropertyEditors;
+using Umbraco.Core.Services;
+using Umbraco.Web.Models.ContentEditing;
+
+namespace Umbraco.Web.Editors
+{
+ ///
+ /// An action filter that wires up the persisted entity of the DataTypeSave model and validates the whole request
+ ///
+ internal sealed class DataTypeValidateAttribute : ActionFilterAttribute
+ {
+ private readonly IDataTypeService _dataTypeService;
+
+ public DataTypeValidateAttribute()
+ {
+ }
+
+ public DataTypeValidateAttribute(IDataTypeService dataTypeService)
+ {
+ if (dataTypeService == null) throw new ArgumentNullException("dataTypeService");
+ _dataTypeService = dataTypeService;
+ }
+
+ private IDataTypeService DataTypeService
+ {
+ get { return _dataTypeService ?? ApplicationContext.Current.Services.DataTypeService; }
+ }
+
+ public override void OnActionExecuting(HttpActionContext actionContext)
+ {
+ var dataType = (DataTypeSave)actionContext.ActionArguments["dataType"];
+
+ //Validate that the property editor exists
+ var propertyEditor = PropertyEditorResolver.Current.GetById(dataType.SelectedEditor);
+ if (propertyEditor == null)
+ {
+ var message = string.Format("Property editor with id: {0} was not found", dataType.SelectedEditor);
+ actionContext.Response = actionContext.Request.CreateErrorResponse(HttpStatusCode.NotFound, message);
+ return;
+ }
+
+ //assign the prop editor to the model
+ dataType.PropertyEditor = propertyEditor;
+
+ //Validate the data type exists or create one if required
+ IDataTypeDefinition persisted;
+ switch (dataType.Action)
+ {
+ case ContentSaveAction.Save:
+ persisted = DataTypeService.GetDataTypeDefinitionById(dataType.Id);
+ if (persisted == null)
+ {
+ var message = string.Format("Data type with id: {0} was not found", dataType.Id);
+ actionContext.Response = actionContext.Request.CreateErrorResponse(HttpStatusCode.NotFound, message);
+ return;
+ }
+ //map the model to the persisted instance
+ Mapper.Map(dataType, persisted);
+ break;
+ case ContentSaveAction.SaveNew:
+ //create the persisted model from mapping the saved model
+ persisted = Mapper.Map(dataType);
+ break;
+ default:
+ throw new HttpResponseException(HttpStatusCode.NotFound);
+ }
+
+ //now assign the persisted entity to the model so we can use it in the action
+ dataType.PersistedDataType = persisted;
+
+ //Validate each field
+ foreach (var preVal in dataType.PreValues)
+ {
+ var postedValue = preVal.Value;
+
+ foreach (var v in propertyEditor.PreValueEditor.Fields.SelectMany(x => x.Validators))
+ {
+ foreach (var result in v.Validate(postedValue, preVal.Key, propertyEditor))
+ {
+ //if there are no member names supplied then we assume that the validation message is for the overall property
+ // not a sub field on the property editor
+ if (!result.MemberNames.Any())
+ {
+ //add a model state error for the entire property
+ actionContext.ModelState.AddModelError(string.Format("{0}.{1}", "Properties", preVal.Key), result.ErrorMessage);
+ }
+ else
+ {
+ //there's assigned field names so we'll combine the field name with the property name
+ // so that we can try to match it up to a real sub field of this editor
+ foreach (var field in result.MemberNames)
+ {
+ actionContext.ModelState.AddModelError(string.Format("{0}.{1}.{2}", "Properties", preVal.Key, field), result.ErrorMessage);
+ }
+ }
+ }
+ }
+ }
+
+ if (actionContext.ModelState.IsValid == false)
+ {
+ //if it is not valid, do not continue and return the model state
+ actionContext.Response = actionContext.Request.CreateErrorResponse(HttpStatusCode.Forbidden, actionContext.ModelState);
+ return;
+ }
+
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Web/Models/ContentEditing/DataTypeSave.cs b/src/Umbraco.Web/Models/ContentEditing/DataTypeSave.cs
index 3652f776b6..4215932716 100644
--- a/src/Umbraco.Web/Models/ContentEditing/DataTypeSave.cs
+++ b/src/Umbraco.Web/Models/ContentEditing/DataTypeSave.cs
@@ -2,6 +2,9 @@
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Runtime.Serialization;
+using Newtonsoft.Json;
+using Umbraco.Core.Models;
+using Umbraco.Core.PropertyEditors;
namespace Umbraco.Web.Models.ContentEditing
{
@@ -25,5 +28,17 @@ namespace Umbraco.Web.Models.ContentEditing
[DataMember(Name = "preValues")]
public IEnumerable PreValues { get; set; }
+ ///
+ /// The real persisted data type
+ ///
+ [JsonIgnore]
+ internal IDataTypeDefinition PersistedDataType { get; set; }
+
+ ///
+ /// The PropertyEditor assigned
+ ///
+ [JsonIgnore]
+ internal PropertyEditor PropertyEditor { get; set; }
+
}
}
\ No newline at end of file
diff --git a/src/Umbraco.Web/Trees/ContentTreeController.cs b/src/Umbraco.Web/Trees/ContentTreeController.cs
index 27e787575e..b5a450638f 100644
--- a/src/Umbraco.Web/Trees/ContentTreeController.cs
+++ b/src/Umbraco.Web/Trees/ContentTreeController.cs
@@ -111,7 +111,7 @@ namespace Umbraco.Web.Trees
// add default actions for *all* users
allowedMenu.AddMenuItem();
- allowedMenu.AddMenuItem(true);
+ allowedMenu.AddMenuItem(true);
return allowedMenu;
}
@@ -155,7 +155,7 @@ namespace Umbraco.Web.Trees
menu.AddMenuItem(true);
menu.AddMenuItem();
- menu.AddMenuItem(true);
+ menu.AddMenuItem(true);
return menu;
}
diff --git a/src/Umbraco.Web/Trees/DataTypeTreeController.cs b/src/Umbraco.Web/Trees/DataTypeTreeController.cs
index 73477e0f71..5907f89fe9 100644
--- a/src/Umbraco.Web/Trees/DataTypeTreeController.cs
+++ b/src/Umbraco.Web/Trees/DataTypeTreeController.cs
@@ -45,8 +45,8 @@ namespace Umbraco.Web.Trees
if (id == Constants.System.Root.ToInvariantString())
{
// root actions
- menu.AddMenuItem();
- menu.AddMenuItem(true);
+ menu.AddMenuItem();
+ menu.AddMenuItem(true);
return menu;
}
diff --git a/src/Umbraco.Web/Trees/MediaTreeController.cs b/src/Umbraco.Web/Trees/MediaTreeController.cs
index 7078e7d2ac..95a39fd3c6 100644
--- a/src/Umbraco.Web/Trees/MediaTreeController.cs
+++ b/src/Umbraco.Web/Trees/MediaTreeController.cs
@@ -47,7 +47,7 @@ namespace Umbraco.Web.Trees
// root actions
menu.AddMenuItem();
menu.AddMenuItem(true);
- menu.AddMenuItem(true);
+ menu.AddMenuItem(true);
return menu;
}
diff --git a/src/Umbraco.Web/Trees/Menu/CreateChildEntity.cs b/src/Umbraco.Web/Trees/Menu/CreateChildEntity.cs
new file mode 100644
index 0000000000..8a26e12aed
--- /dev/null
+++ b/src/Umbraco.Web/Trees/Menu/CreateChildEntity.cs
@@ -0,0 +1,10 @@
+namespace Umbraco.Web.Trees.Menu
+{
+ ///
+ /// Represents the refresh node menu item
+ ///
+ [ActionMenuItem("umbracoMenuActions")]
+ public sealed class CreateChildEntity : ActionMenuItem
+ {
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Web/Trees/Menu/RefreshNodeMenuItem.cs b/src/Umbraco.Web/Trees/Menu/RefreshNode.cs
similarity index 72%
rename from src/Umbraco.Web/Trees/Menu/RefreshNodeMenuItem.cs
rename to src/Umbraco.Web/Trees/Menu/RefreshNode.cs
index 0eb78a0eb5..5f1d06bf4e 100644
--- a/src/Umbraco.Web/Trees/Menu/RefreshNodeMenuItem.cs
+++ b/src/Umbraco.Web/Trees/Menu/RefreshNode.cs
@@ -1,10 +1,10 @@
-namespace Umbraco.Web.Trees.Menu
-{
- ///
- /// Represents the refresh node menu item
- ///
- [ActionMenuItem("umbracoMenuActions")]
- public sealed class RefreshNodeMenuItem : ActionMenuItem
- {
- }
+namespace Umbraco.Web.Trees.Menu
+{
+ ///
+ /// Represents the refresh node menu item
+ ///
+ [ActionMenuItem("umbracoMenuActions")]
+ public sealed class RefreshNode : ActionMenuItem
+ {
+ }
}
\ No newline at end of file
diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj
index e1948163dd..651a651cdc 100644
--- a/src/Umbraco.Web/Umbraco.Web.csproj
+++ b/src/Umbraco.Web/Umbraco.Web.csproj
@@ -299,6 +299,7 @@
+
@@ -320,6 +321,7 @@
+
@@ -379,7 +381,7 @@
-
+
diff --git a/src/umbraco.cms/Actions/ActionRefresh.cs b/src/umbraco.cms/Actions/ActionRefresh.cs
index 9aa0a4fe78..e94d4d2fed 100644
--- a/src/umbraco.cms/Actions/ActionRefresh.cs
+++ b/src/umbraco.cms/Actions/ActionRefresh.cs
@@ -9,7 +9,7 @@ namespace umbraco.BusinessLogic.Actions
/// Concerns only the tree itself and thus you should not handle
/// this action from without umbraco.
///
- [LegacyActionMenuItem("umbracoMenuActions", "RefreshNodeMenuItem")]
+ [LegacyActionMenuItem("umbracoMenuActions", "RefreshNode")]
public class ActionRefresh : IAction
{
//create singleton