diff --git a/src/Umbraco.Core/Services/ContentTypeService.cs b/src/Umbraco.Core/Services/ContentTypeService.cs
index f3017089d7..afd7da9efe 100644
--- a/src/Umbraco.Core/Services/ContentTypeService.cs
+++ b/src/Umbraco.Core/Services/ContentTypeService.cs
@@ -347,6 +347,35 @@ namespace Umbraco.Core.Services
}
}
+ ///
+ /// Gets an object by its Id
+ ///
+ /// Id of the to retrieve
+ ///
+ public IMemberType GetMemberType(int id)
+ {
+ using (var repository = _repositoryFactory.CreateMemberTypeRepository(_uowProvider.GetUnitOfWork()))
+ {
+ return repository.Get(id);
+ }
+ }
+
+ ///
+ /// Gets an object by its Alias
+ ///
+ /// Alias of the to retrieve
+ ///
+ public IMemberType GetMemberType(string alias)
+ {
+ using (var repository = _repositoryFactory.CreateMemberTypeRepository(_uowProvider.GetUnitOfWork()))
+ {
+ var query = Query.Builder.Where(x => x.Alias == alias);
+ var contentTypes = repository.GetByQuery(query);
+
+ return contentTypes.FirstOrDefault();
+ }
+ }
+
///
/// Gets an object by its Id
///
diff --git a/src/Umbraco.Core/Services/IContentTypeService.cs b/src/Umbraco.Core/Services/IContentTypeService.cs
index 9e7849e33c..9f596e465e 100644
--- a/src/Umbraco.Core/Services/IContentTypeService.cs
+++ b/src/Umbraco.Core/Services/IContentTypeService.cs
@@ -67,6 +67,20 @@ namespace Umbraco.Core.Services
/// Optional Id of the User deleting the ContentTypes
void Delete(IEnumerable contentTypes, int userId = 0);
+ ///
+ /// Gets an object by its Id
+ ///
+ /// Id of the to retrieve
+ ///
+ IMemberType GetMemberType(int id);
+
+ ///
+ /// Gets an object by its Alias
+ ///
+ /// Alias of the to retrieve
+ ///
+ IMemberType GetMemberType(string alias);
+
///
/// Gets an object by its Id
///
diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/content.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/content.resource.js
index ad4cff3c70..45b696edb2 100644
--- a/src/Umbraco.Web.UI.Client/src/common/resources/content.resource.js
+++ b/src/Umbraco.Web.UI.Client/src/common/resources/content.resource.js
@@ -27,11 +27,17 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) {
/** internal method process the saving of data and post processing the result */
function saveContentItem(content, action, files) {
- return umbRequestHelper.postSaveContent(
- umbRequestHelper.getApiUrl(
+ return umbRequestHelper.postSaveContent({
+ restApiUrl: umbRequestHelper.getApiUrl(
"contentApiBaseUrl",
"PostSave"),
- content, action, files);
+ content: content,
+ action: action,
+ files: files,
+ dataFormatter: function (c, a) {
+ return umbDataFormatter.formatContentPostData(c, a);
+ }
+ });
}
return {
diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/media.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/media.resource.js
index fc9cc117a0..951a4d182f 100644
--- a/src/Umbraco.Web.UI.Client/src/common/resources/media.resource.js
+++ b/src/Umbraco.Web.UI.Client/src/common/resources/media.resource.js
@@ -7,11 +7,17 @@ function mediaResource($q, $http, umbDataFormatter, umbRequestHelper) {
/** internal method process the saving of data and post processing the result */
function saveMediaItem(content, action, files) {
- return umbRequestHelper.postSaveContent(
- umbRequestHelper.getApiUrl(
+ return umbRequestHelper.postSaveContent({
+ restApiUrl: umbRequestHelper.getApiUrl(
"mediaApiBaseUrl",
"PostSave"),
- content, action, files);
+ content: content,
+ action: action,
+ files: files,
+ dataFormatter: function (c, a) {
+ return umbDataFormatter.formatMediaPostData(c, a);
+ }
+ });
}
return {
diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/member.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/member.resource.js
index f5f32037ad..d879aa322c 100644
--- a/src/Umbraco.Web.UI.Client/src/common/resources/member.resource.js
+++ b/src/Umbraco.Web.UI.Client/src/common/resources/member.resource.js
@@ -7,11 +7,18 @@ function memberResource($q, $http, umbDataFormatter, umbRequestHelper) {
/** internal method process the saving of data and post processing the result */
function saveMember(content, action, files) {
- return umbRequestHelper.postSaveContent(
- umbRequestHelper.getApiUrl(
+
+ return umbRequestHelper.postSaveContent({
+ restApiUrl: umbRequestHelper.getApiUrl(
"memberApiBaseUrl",
"PostSave"),
- content, action, files);
+ content: content,
+ action: action,
+ files: files,
+ dataFormatter: function(c, a) {
+ return umbDataFormatter.formatMemberPostData(c, a);
+ }
+ });
}
return {
diff --git a/src/Umbraco.Web.UI.Client/src/common/services/umbrequesthelper.service.js b/src/Umbraco.Web.UI.Client/src/common/services/umbrequesthelper.service.js
index 9b52da35ad..d44bb9ccb5 100644
--- a/src/Umbraco.Web.UI.Client/src/common/services/umbrequesthelper.service.js
+++ b/src/Umbraco.Web.UI.Client/src/common/services/umbrequesthelper.service.js
@@ -151,26 +151,43 @@ function umbRequestHelper($http, $q, umbDataFormatter, angularHelper, dialogServ
},
/** Used for saving media/content specifically */
- postSaveContent: function (restApiUrl, content, action, files) {
+ postSaveContent: function (args) {
+
+ if (!args.restApiUrl) {
+ throw "args.restApiUrl is a required argument";
+ }
+ if (!args.content) {
+ throw "args.content is a required argument";
+ }
+ if (!args.action) {
+ throw "args.action is a required argument";
+ }
+ if (!args.files) {
+ throw "args.files is a required argument";
+ }
+ if (!args.dataFormatter) {
+ throw "args.dataFormatter is a required argument";
+ }
+
var deferred = $q.defer();
//save the active tab id so we can set it when the data is returned.
- var activeTab = _.find(content.tabs, function (item) {
+ var activeTab = _.find(args.content.tabs, function (item) {
return item.active;
});
- var activeTabIndex = (activeTab === undefined ? 0 : _.indexOf(content.tabs, activeTab));
+ var activeTabIndex = (activeTab === undefined ? 0 : _.indexOf(args.content.tabs, activeTab));
//save the data
this.postMultiPartRequest(
- restApiUrl,
- { key: "contentItem", value: umbDataFormatter.formatContentPostData(content, action) },
+ args.restApiUrl,
+ { key: "contentItem", value: args.dataFormatter(args.content, args.action) },
function (data, formData) {
//now add all of the assigned files
- for (var f in files) {
+ for (var f in args.files) {
//each item has a property id and the file object, we'll ensure that the id is suffixed to the key
// so we know which property it belongs to on the server side
- formData.append("file_" + files[f].id, files[f].file);
+ formData.append("file_" + args.files[f].id, args.files[f].file);
}
},
diff --git a/src/Umbraco.Web.UI.Client/src/common/services/util.service.js b/src/Umbraco.Web.UI.Client/src/common/services/util.service.js
index 21e81d1ac3..09f4ecf067 100644
--- a/src/Umbraco.Web.UI.Client/src/common/services/util.service.js
+++ b/src/Umbraco.Web.UI.Client/src/common/services/util.service.js
@@ -196,24 +196,45 @@ function umbDataFormatter() {
return saveModel;
},
- /** formats the display model used to display the content to the model used to save the content */
- formatContentPostData: function (displayModel, action) {
+ /** formats the display model used to display the member to the model used to save the member */
+ formatMemberPostData: function(displayModel, action) {
+ //this is basically the same as for media but we need to explicitly add the username,email to the save model
+ var saveModel = this.formatMediaPostData(displayModel, action);
+
+ var genericTab = _.find(displayModel.tabs, function (item) {
+ return item.id === 0;
+ });
+
+ var propLogin = _.find(genericTab.properties, function (item) {
+ return item.alias === "_umb_login";
+ });
+ var propEmail = _.find(genericTab.properties, function (item) {
+ return item.alias === "_umb_email";
+ });
+ saveModel.email = propEmail.value;
+ saveModel.username = propLogin.value;
+
+ return saveModel;
+ },
+
+ /** formats the display model used to display the media to the model used to save the media */
+ formatMediaPostData: function(displayModel, action) {
//NOTE: the display model inherits from the save model so we can in theory just post up the display model but
// we don't want to post all of the data as it is unecessary.
var saveModel = {
id: displayModel.id,
properties: [],
name: displayModel.name,
- contentTypeAlias : displayModel.contentTypeAlias,
+ contentTypeAlias: displayModel.contentTypeAlias,
parentId: displayModel.parentId,
//set the action on the save model
action: action
};
-
+
_.each(displayModel.tabs, function (tab) {
-
+
_.each(tab.properties, function (prop) {
-
+
//don't include the custom generic tab properties
if (!prop.alias.startsWith("_umb_")) {
saveModel.properties.push({
@@ -222,25 +243,36 @@ function umbDataFormatter() {
value: prop.value
});
}
- else {
- //here we need to map some of our internal properties to the content save item
-
- switch (prop.alias) {
- case "_umb_expiredate":
- saveModel.expireDate = prop.value;
- break;
- case "_umb_releasedate":
- saveModel.releaseDate = prop.value;
- break;
- case "_umb_template":
- saveModel.templateAlias = prop.value;
- break;
- }
- }
});
});
+ return saveModel;
+ },
+
+ /** formats the display model used to display the content to the model used to save the content */
+ formatContentPostData: function (displayModel, action) {
+
+ //this is basically the same as for media but we need to explicitly add some extra properties
+ var saveModel = this.formatMediaPostData(displayModel, action);
+
+ var genericTab = _.find(displayModel.tabs, function (item) {
+ return item.id === 0;
+ });
+
+ var propExpireDate = _.find(genericTab.properties, function(item) {
+ return item.alias === "_umb_expiredate";
+ });
+ var propReleaseDate = _.find(genericTab.properties, function (item) {
+ return item.alias === "_umb_releasedate";
+ });
+ var propTemplate = _.find(genericTab.properties, function (item) {
+ return item.alias === "_umb_template";
+ });
+ saveModel.expireDate = propExpireDate.value;
+ saveModel.releaseDate = propReleaseDate.value;
+ saveModel.templateAlias = propTemplate.value;
+
return saveModel;
}
};
diff --git a/src/Umbraco.Web/Editors/ContentController.cs b/src/Umbraco.Web/Editors/ContentController.cs
index 39ca4704b4..d27b8b268f 100644
--- a/src/Umbraco.Web/Editors/ContentController.cs
+++ b/src/Umbraco.Web/Editors/ContentController.cs
@@ -166,7 +166,7 @@ namespace Umbraco.Web.Editors
[ContentPostValidate]
public ContentItemDisplay PostSave(
[ModelBinder(typeof(ContentItemBinder))]
- ContentItemSave contentItem)
+ ContentItemSave contentItem)
{
//If we've reached here it means:
// * Our model has been bound
diff --git a/src/Umbraco.Web/Editors/ContentControllerBase.cs b/src/Umbraco.Web/Editors/ContentControllerBase.cs
index 6413173ce8..73e66bcc44 100644
--- a/src/Umbraco.Web/Editors/ContentControllerBase.cs
+++ b/src/Umbraco.Web/Editors/ContentControllerBase.cs
@@ -52,7 +52,7 @@ namespace Umbraco.Web.Editors
return errorResponse;
}
- protected void UpdateName(ContentItemSave contentItem)
+ protected void UpdateName(ContentBaseItemSave contentItem)
where TPersisted : IContentBase
{
//Don't update the name if it is empty
@@ -78,7 +78,7 @@ namespace Umbraco.Web.Editors
return null;
}
- protected void MapPropertyValues(ContentItemSave contentItem)
+ protected void MapPropertyValues(ContentBaseItemSave contentItem)
where TPersisted : IContentBase
{
//Map the property values
diff --git a/src/Umbraco.Web/Editors/ContentPostValidateAttribute.cs b/src/Umbraco.Web/Editors/ContentPostValidateAttribute.cs
index 1736b57dd9..79a6dd3836 100644
--- a/src/Umbraco.Web/Editors/ContentPostValidateAttribute.cs
+++ b/src/Umbraco.Web/Editors/ContentPostValidateAttribute.cs
@@ -53,7 +53,7 @@ namespace Umbraco.Web.Editors
public override void OnActionExecuting(HttpActionContext actionContext)
{
- var contentItem = (ContentItemSave)actionContext.ActionArguments["contentItem"];
+ var contentItem = (ContentItemSave)actionContext.ActionArguments["contentItem"];
//We now need to validate that the user is allowed to be doing what they are doing.
//Based on the action we need to check different permissions.
diff --git a/src/Umbraco.Web/Editors/DataTypeValidateAttribute.cs b/src/Umbraco.Web/Editors/DataTypeValidateAttribute.cs
index a5be7c118d..2ae24717bd 100644
--- a/src/Umbraco.Web/Editors/DataTypeValidateAttribute.cs
+++ b/src/Umbraco.Web/Editors/DataTypeValidateAttribute.cs
@@ -59,7 +59,7 @@ namespace Umbraco.Web.Editors
switch (dataType.Action)
{
case ContentSaveAction.Save:
- persisted = DataTypeService.GetDataTypeDefinitionById(dataType.Id);
+ persisted = DataTypeService.GetDataTypeDefinitionById(Convert.ToInt32(dataType.Id));
if (persisted == null)
{
var message = string.Format("Data type with id: {0} was not found", dataType.Id);
diff --git a/src/Umbraco.Web/Editors/MediaController.cs b/src/Umbraco.Web/Editors/MediaController.cs
index b32b709df5..4f21a4e8a3 100644
--- a/src/Umbraco.Web/Editors/MediaController.cs
+++ b/src/Umbraco.Web/Editors/MediaController.cs
@@ -201,7 +201,7 @@ namespace Umbraco.Web.Editors
[MediaPostValidate]
public MediaItemDisplay PostSave(
[ModelBinder(typeof(MediaItemBinder))]
- ContentItemSave contentItem)
+ MediaItemSave contentItem)
{
//If we've reached here it means:
// * Our model has been bound
diff --git a/src/Umbraco.Web/Editors/MediaPostValidateAttribute.cs b/src/Umbraco.Web/Editors/MediaPostValidateAttribute.cs
index 4790a9122f..31a581eac2 100644
--- a/src/Umbraco.Web/Editors/MediaPostValidateAttribute.cs
+++ b/src/Umbraco.Web/Editors/MediaPostValidateAttribute.cs
@@ -45,7 +45,7 @@ namespace Umbraco.Web.Editors
public override void OnActionExecuting(HttpActionContext actionContext)
{
- var mediaItem = (ContentItemSave)actionContext.ActionArguments["contentItem"];
+ var mediaItem = (MediaItemSave)actionContext.ActionArguments["contentItem"];
//We now need to validate that the user is allowed to be doing what they are doing.
//Then if it is new, we need to lookup those permissions on the parent.
diff --git a/src/Umbraco.Web/Editors/MemberController.cs b/src/Umbraco.Web/Editors/MemberController.cs
index a67f472f1a..a424324b3c 100644
--- a/src/Umbraco.Web/Editors/MemberController.cs
+++ b/src/Umbraco.Web/Editors/MemberController.cs
@@ -4,6 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web.Http;
+using System.Web.Http.ModelBinding;
using AutoMapper;
using Examine.LuceneEngine.SearchCriteria;
using Examine.SearchCriteria;
@@ -11,7 +12,9 @@ using Umbraco.Core.Models;
using Umbraco.Web.WebApi;
using Umbraco.Web.Models.ContentEditing;
using Umbraco.Web.Mvc;
+using Umbraco.Web.WebApi.Binders;
using Umbraco.Web.WebApi.Filters;
+using umbraco;
using Constants = Umbraco.Core.Constants;
using Examine;
using System.Web.Security;
@@ -67,5 +70,65 @@ namespace Umbraco.Web.Editors
}
}
+
+ ///
+ /// Saves member
+ ///
+ ///
+ [FileUploadCleanupFilter]
+ public MemberDisplay PostSave(
+ [ModelBinder(typeof(MemberBinder))]
+ MemberSave contentItem)
+ {
+ //If we've reached here it means:
+ // * Our model has been bound
+ // * and validated
+ // * any file attachments have been saved to their temporary location for us to use
+ // * we have a reference to the DTO object and the persisted object
+ // * Permissions are valid
+
+ UpdateName(contentItem);
+
+ MapPropertyValues(contentItem);
+
+ //We need to manually check the validation results here because:
+ // * We still need to save the entity even if there are validation value errors
+ // * Depending on if the entity is new, and if there are non property validation errors (i.e. the name is null)
+ // then we cannot continue saving, we can only display errors
+ // * If there are validation errors and they were attempting to publish, we can only save, NOT publish and display
+ // a message indicating this
+ if (!ModelState.IsValid)
+ {
+ if (ValidationHelper.ModelHasRequiredForPersistenceErrors(contentItem)
+ && (contentItem.Action == ContentSaveAction.SaveNew))
+ {
+ //ok, so the absolute mandatory data is invalid and it's new, we cannot actually continue!
+ // add the modelstate to the outgoing object and throw validation response
+ var forDisplay = Mapper.Map(contentItem.PersistedContent);
+ forDisplay.Errors = ModelState.ToErrorDictionary();
+ throw new HttpResponseException(Request.CreateValidationErrorResponse(forDisplay));
+ }
+ }
+
+ //save the item
+ Services.MemberService.Save(contentItem.PersistedContent);
+
+ //return the updated model
+ var display = Mapper.Map(contentItem.PersistedContent);
+
+ //lasty, if it is not valid, add the modelstate to the outgoing object and throw a 403
+ HandleInvalidModelState(display);
+
+ //put the correct msgs in
+ switch (contentItem.Action)
+ {
+ case ContentSaveAction.Save:
+ case ContentSaveAction.SaveNew:
+ display.AddSuccessNotification(ui.Text("speechBubbles", "editMemberSaved"), ui.Text("speechBubbles", "editMemberSaved"));
+ break;
+ }
+
+ return display;
+ }
}
}
diff --git a/src/Umbraco.Web/Models/ContentEditing/ContentItemBasic.cs b/src/Umbraco.Web/Models/ContentEditing/ContentItemBasic.cs
index 927983e4fe..560f997bde 100644
--- a/src/Umbraco.Web/Models/ContentEditing/ContentItemBasic.cs
+++ b/src/Umbraco.Web/Models/ContentEditing/ContentItemBasic.cs
@@ -34,7 +34,7 @@ namespace Umbraco.Web.Models.ContentEditing
[DataMember(Name = "sortOrder")]
public int SortOrder { get; set; }
-
+
protected bool Equals(ContentItemBasic other)
{
return Id == other.Id;
@@ -50,7 +50,7 @@ namespace Umbraco.Web.Models.ContentEditing
public override int GetHashCode()
{
- return Id;
+ return Id.GetHashCode();
}
}
diff --git a/src/Umbraco.Web/Models/ContentEditing/ContentItemSave.cs b/src/Umbraco.Web/Models/ContentEditing/ContentItemSave.cs
index 9c04a3adcf..6f05f38e7f 100644
--- a/src/Umbraco.Web/Models/ContentEditing/ContentItemSave.cs
+++ b/src/Umbraco.Web/Models/ContentEditing/ContentItemSave.cs
@@ -8,13 +8,13 @@ using Umbraco.Core.Models;
namespace Umbraco.Web.Models.ContentEditing
{
///
- /// A model representing a content item to be saved
+ /// A model representing a content base item to be saved
///
[DataContract(Name = "content", Namespace = "")]
- public class ContentItemSave : ContentItemBasic, IHaveUploadedFiles
- where TPersisted : IContentBase
+ public abstract class ContentBaseItemSave : ContentItemBasic, IHaveUploadedFiles
+ where TPersisted : IContentBase
{
- public ContentItemSave()
+ protected ContentBaseItemSave()
{
UploadedFiles = new List();
}
@@ -26,6 +26,25 @@ namespace Umbraco.Web.Models.ContentEditing
[Required]
public ContentSaveAction Action { get; set; }
+ [IgnoreDataMember]
+ public List UploadedFiles { get; private set; }
+ }
+
+ ///
+ /// A model representing a media item to be saved
+ ///
+ [DataContract(Name = "content", Namespace = "")]
+ public class MediaItemSave : ContentBaseItemSave
+ {
+
+ }
+
+ ///
+ /// A model representing a content item to be saved
+ ///
+ [DataContract(Name = "content", Namespace = "")]
+ public class ContentItemSave : ContentBaseItemSave
+ {
///
/// The template alias to save
///
@@ -38,10 +57,5 @@ namespace Umbraco.Web.Models.ContentEditing
[DataMember(Name = "expireDate")]
public DateTime? ExpireDate { get; set; }
- ///
- /// The collection of files uploaded
- ///
- [JsonIgnore]
- public List UploadedFiles { get; private set; }
}
}
\ No newline at end of file
diff --git a/src/Umbraco.Web/Models/ContentEditing/EntityBasic.cs b/src/Umbraco.Web/Models/ContentEditing/EntityBasic.cs
index 8e08352ecb..d07955060f 100644
--- a/src/Umbraco.Web/Models/ContentEditing/EntityBasic.cs
+++ b/src/Umbraco.Web/Models/ContentEditing/EntityBasic.cs
@@ -18,7 +18,7 @@ namespace Umbraco.Web.Models.ContentEditing
[DataMember(Name = "id", IsRequired = true)]
[Required]
- public int Id { get; set; }
+ public object Id { get; set; }
[DataMember(Name = "icon")]
public string Icon { get; set; }
diff --git a/src/Umbraco.Web/Models/ContentEditing/MemberSave.cs b/src/Umbraco.Web/Models/ContentEditing/MemberSave.cs
new file mode 100644
index 0000000000..198d489d83
--- /dev/null
+++ b/src/Umbraco.Web/Models/ContentEditing/MemberSave.cs
@@ -0,0 +1,20 @@
+using System.Runtime.Serialization;
+using Umbraco.Core.Models;
+using Umbraco.Core.Models.Validation;
+
+namespace Umbraco.Web.Models.ContentEditing
+{
+ ///
+ /// A model representing a member to be saved
+ ///
+ public class MemberSave : ContentBaseItemSave
+ {
+ [DataMember(Name = "username", IsRequired = true)]
+ [RequiredForPersistence(AllowEmptyStrings = false, ErrorMessage = "Required")]
+ public string Username { get; set; }
+
+ [DataMember(Name = "email", IsRequired = true)]
+ [RequiredForPersistence(AllowEmptyStrings = false, ErrorMessage = "Required")]
+ public string Email { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Web/Models/Mapping/MemberModelMapper.cs b/src/Umbraco.Web/Models/Mapping/MemberModelMapper.cs
index d1689e6eb2..61a7a07c50 100644
--- a/src/Umbraco.Web/Models/Mapping/MemberModelMapper.cs
+++ b/src/Umbraco.Web/Models/Mapping/MemberModelMapper.cs
@@ -45,7 +45,7 @@ namespace Umbraco.Web.Models.Mapping
expression => expression.MapFrom(content => content.ContentType.Alias));
//FROM IMember TO ContentItemDto
- config.CreateMap>()
+ config.CreateMap>()
.ForMember(
dto => dto.Owner,
expression => expression.ResolveUsing>());
@@ -77,7 +77,7 @@ namespace Umbraco.Web.Models.Mapping
},
new ContentPropertyDisplay
{
- Alias = string.Format("{0}template", Constants.PropertyEditors.InternalGenericPropertiesPrefix),
+ Alias = string.Format("{0}email", Constants.PropertyEditors.InternalGenericPropertiesPrefix),
Label = ui.Text("general", "email"),
Value = display.Email,
View = "textbox"
diff --git a/src/Umbraco.Web/Models/Mapping/TabsAndPropertiesResolver.cs b/src/Umbraco.Web/Models/Mapping/TabsAndPropertiesResolver.cs
index be4246d71a..25038fc08e 100644
--- a/src/Umbraco.Web/Models/Mapping/TabsAndPropertiesResolver.cs
+++ b/src/Umbraco.Web/Models/Mapping/TabsAndPropertiesResolver.cs
@@ -46,7 +46,7 @@ namespace Umbraco.Web.Models.Mapping
{
Alias = string.Format("{0}id", Constants.PropertyEditors.InternalGenericPropertiesPrefix),
Label = "Id",
- Value = display.Id.ToInvariantString(),
+ Value = Convert.ToInt32(display.Id).ToInvariantString(),
View = labelEditor
},
new ContentPropertyDisplay
diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj
index 4b64498c0b..26941aa33a 100644
--- a/src/Umbraco.Web/Umbraco.Web.csproj
+++ b/src/Umbraco.Web/Umbraco.Web.csproj
@@ -315,6 +315,7 @@
+
@@ -369,6 +370,7 @@
+
diff --git a/src/Umbraco.Web/WebApi/Binders/ContentItemBaseBinder.cs b/src/Umbraco.Web/WebApi/Binders/ContentItemBaseBinder.cs
index d1e843b6ef..2d374fc529 100644
--- a/src/Umbraco.Web/WebApi/Binders/ContentItemBaseBinder.cs
+++ b/src/Umbraco.Web/WebApi/Binders/ContentItemBaseBinder.cs
@@ -33,8 +33,9 @@ namespace Umbraco.Web.WebApi.Binders
///
/// Binds the content model to the controller action for the posted multi-part Post
///
- internal abstract class ContentItemBaseBinder : IModelBinder
+ internal abstract class ContentItemBaseBinder : IModelBinder
where TPersisted : class, IContentBase
+ where TModelSave : ContentBaseItemSave
{
protected ApplicationContext ApplicationContext { get; private set; }
@@ -69,7 +70,7 @@ namespace Umbraco.Web.WebApi.Binders
}
//now that everything is binded, validate the properties
- var contentItemValidator = new ContentItemValidationHelper(ApplicationContext);
+ var contentItemValidator = new ContentItemValidationHelper(ApplicationContext);
contentItemValidator.ValidateItem(actionContext, x.Result);
bindingContext.Model = x.Result;
@@ -87,7 +88,7 @@ namespace Umbraco.Web.WebApi.Binders
///
///
///
- private async Task> GetModel(HttpActionContext actionContext, ModelBindingContext bindingContext, MultipartFormDataStreamProvider provider)
+ private async Task GetModel(HttpActionContext actionContext, ModelBindingContext bindingContext, MultipartFormDataStreamProvider provider)
{
var request = actionContext.Request;
@@ -115,13 +116,13 @@ namespace Umbraco.Web.WebApi.Binders
var contentItem = result.FormData["contentItem"];
//deserialize into our model
- var model = JsonConvert.DeserializeObject>(contentItem);
+ var model = JsonConvert.DeserializeObject(contentItem);
//get the default body validator and validate the object
var bodyValidator = actionContext.ControllerContext.Configuration.Services.GetBodyModelValidator();
var metadataProvider = actionContext.ControllerContext.Configuration.Services.GetModelMetadataProvider();
//all validation errors will not contain a prefix
- bodyValidator.Validate(model, typeof (ContentItemSave), metadataProvider, actionContext, "");
+ bodyValidator.Validate(model, typeof(TModelSave), metadataProvider, actionContext, "");
//get the files
foreach (var file in result.FileData)
@@ -187,7 +188,7 @@ namespace Umbraco.Web.WebApi.Binders
///
///
///
- private static void MapPropertyValuesFromSaved(ContentItemSave saveModel, ContentItemDto dto)
+ private static void MapPropertyValuesFromSaved(TModelSave saveModel, ContentItemDto dto)
{
foreach (var p in saveModel.Properties)
{
@@ -195,8 +196,8 @@ namespace Umbraco.Web.WebApi.Binders
}
}
- protected abstract TPersisted GetExisting(ContentItemSave model);
- protected abstract TPersisted CreateNew(ContentItemSave model);
- protected abstract ContentItemDto MapFromPersisted(ContentItemSave model);
+ protected abstract TPersisted GetExisting(TModelSave model);
+ protected abstract TPersisted CreateNew(TModelSave model);
+ protected abstract ContentItemDto MapFromPersisted(TModelSave model);
}
}
\ No newline at end of file
diff --git a/src/Umbraco.Web/WebApi/Binders/ContentItemBinder.cs b/src/Umbraco.Web/WebApi/Binders/ContentItemBinder.cs
index c3c3e2bf84..5afc7cee19 100644
--- a/src/Umbraco.Web/WebApi/Binders/ContentItemBinder.cs
+++ b/src/Umbraco.Web/WebApi/Binders/ContentItemBinder.cs
@@ -7,7 +7,7 @@ using Umbraco.Web.Models.Mapping;
namespace Umbraco.Web.WebApi.Binders
{
- internal class ContentItemBinder : ContentItemBaseBinder
+ internal class ContentItemBinder : ContentItemBaseBinder
{
public ContentItemBinder(ApplicationContext applicationContext)
@@ -23,12 +23,12 @@ namespace Umbraco.Web.WebApi.Binders
{
}
- protected override IContent GetExisting(ContentItemSave model)
+ protected override IContent GetExisting(ContentItemSave model)
{
- return ApplicationContext.Services.ContentService.GetById(model.Id);
+ return ApplicationContext.Services.ContentService.GetById(Convert.ToInt32(model.Id));
}
- protected override IContent CreateNew(ContentItemSave model)
+ protected override IContent CreateNew(ContentItemSave model)
{
var contentType = ApplicationContext.Services.ContentTypeService.GetContentType(model.ContentTypeAlias);
if (contentType == null)
@@ -38,7 +38,7 @@ namespace Umbraco.Web.WebApi.Binders
return new Content(model.Name, model.ParentId, contentType);
}
- protected override ContentItemDto MapFromPersisted(ContentItemSave model)
+ protected override ContentItemDto MapFromPersisted(ContentItemSave model)
{
return Mapper.Map>(model.PersistedContent);
}
diff --git a/src/Umbraco.Web/WebApi/Binders/MediaItemBinder.cs b/src/Umbraco.Web/WebApi/Binders/MediaItemBinder.cs
index 81f7bba8fb..726994d43e 100644
--- a/src/Umbraco.Web/WebApi/Binders/MediaItemBinder.cs
+++ b/src/Umbraco.Web/WebApi/Binders/MediaItemBinder.cs
@@ -7,7 +7,7 @@ using Umbraco.Web.Models.Mapping;
namespace Umbraco.Web.WebApi.Binders
{
- internal class MediaItemBinder : ContentItemBaseBinder
+ internal class MediaItemBinder : ContentItemBaseBinder
{
public MediaItemBinder(ApplicationContext applicationContext)
: base(applicationContext)
@@ -22,12 +22,12 @@ namespace Umbraco.Web.WebApi.Binders
{
}
- protected override IMedia GetExisting(ContentItemSave model)
+ protected override IMedia GetExisting(MediaItemSave model)
{
- return ApplicationContext.Services.MediaService.GetById(model.Id);
+ return ApplicationContext.Services.MediaService.GetById(Convert.ToInt32(model.Id));
}
- protected override IMedia CreateNew(ContentItemSave model)
+ protected override IMedia CreateNew(MediaItemSave model)
{
var contentType = ApplicationContext.Services.ContentTypeService.GetMediaType(model.ContentTypeAlias);
if (contentType == null)
@@ -37,7 +37,7 @@ namespace Umbraco.Web.WebApi.Binders
return new Core.Models.Media(model.Name, model.ParentId, contentType);
}
- protected override ContentItemDto MapFromPersisted(ContentItemSave model)
+ protected override ContentItemDto MapFromPersisted(MediaItemSave model)
{
return Mapper.Map>(model.PersistedContent);
}
diff --git a/src/Umbraco.Web/WebApi/Binders/MemberBinder.cs b/src/Umbraco.Web/WebApi/Binders/MemberBinder.cs
new file mode 100644
index 0000000000..ee02c4e076
--- /dev/null
+++ b/src/Umbraco.Web/WebApi/Binders/MemberBinder.cs
@@ -0,0 +1,44 @@
+using System;
+using AutoMapper;
+using Umbraco.Core;
+using Umbraco.Core.Models;
+using Umbraco.Web.Models.ContentEditing;
+
+namespace Umbraco.Web.WebApi.Binders
+{
+ internal class MemberBinder : ContentItemBaseBinder
+ {
+ public MemberBinder(ApplicationContext applicationContext)
+ : base(applicationContext)
+ {
+ }
+
+ ///
+ /// Constructor
+ ///
+ public MemberBinder()
+ : this(ApplicationContext.Current)
+ {
+ }
+
+ protected override IMember GetExisting(MemberSave model)
+ {
+ return ApplicationContext.Services.MemberService.GetByUsername(model.Username);
+ }
+
+ protected override IMember CreateNew(MemberSave model)
+ {
+ var contentType = ApplicationContext.Services.ContentTypeService.GetMemberType(model.ContentTypeAlias);
+ if (contentType == null)
+ {
+ throw new InvalidOperationException("No member type found wth alias " + model.ContentTypeAlias);
+ }
+ return new Member(model.Name, model.ParentId, contentType, new PropertyCollection());
+ }
+
+ protected override ContentItemDto MapFromPersisted(MemberSave model)
+ {
+ return Mapper.Map>(model.PersistedContent);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Web/WebApi/Filters/ContentItemValidationHelper.cs b/src/Umbraco.Web/WebApi/Filters/ContentItemValidationHelper.cs
index adc12b58d7..a68eb2cbbf 100644
--- a/src/Umbraco.Web/WebApi/Filters/ContentItemValidationHelper.cs
+++ b/src/Umbraco.Web/WebApi/Filters/ContentItemValidationHelper.cs
@@ -16,12 +16,14 @@ namespace Umbraco.Web.WebApi.Filters
/// A validation helper class used with ContentItemValidationFilterAttribute to be shared between content, media, etc...
///
///
+ ///
///
/// If any severe errors occur then the response gets set to an error and execution will not continue. Property validation
/// errors will just be added to the ModelState.
///
- internal class ContentItemValidationHelper
+ internal class ContentItemValidationHelper
where TPersisted : class, IContentBase
+ where TModelSave : ContentBaseItemSave
{
private readonly ApplicationContext _applicationContext;
@@ -38,10 +40,10 @@ namespace Umbraco.Web.WebApi.Filters
public void ValidateItem(HttpActionContext actionContext, string argumentName)
{
- var contentItem = actionContext.ActionArguments[argumentName] as ContentItemSave;
+ var contentItem = actionContext.ActionArguments[argumentName] as TModelSave;
if (contentItem == null)
{
- actionContext.Response = actionContext.Request.CreateErrorResponse(HttpStatusCode.BadRequest, "No " + typeof(ContentItemSave) + " found in request");
+ actionContext.Response = actionContext.Request.CreateErrorResponse(HttpStatusCode.BadRequest, "No " + typeof(TModelSave) + " found in request");
return;
}
@@ -49,7 +51,7 @@ namespace Umbraco.Web.WebApi.Filters
}
- public void ValidateItem(HttpActionContext actionContext, ContentItemSave contentItem)
+ public void ValidateItem(HttpActionContext actionContext, TModelSave contentItem)
{
//now do each validation step
if (ValidateExistingContent(contentItem, actionContext) == false) return;
@@ -119,7 +121,7 @@ namespace Umbraco.Web.WebApi.Filters
if (editor == null)
{
var message = string.Format("The property editor with alias: {0} was not found for property with id {1}", p.DataType.PropertyEditorAlias, p.Id);
- LogHelper.Warn>(message);
+ LogHelper.Warn>(message);
//actionContext.Response = actionContext.Request.CreateErrorResponse(HttpStatusCode.NotFound, message);
//return false;
continue;
diff --git a/src/Umbraco.Web/WebApi/Filters/FilterAllowedOutgoingContentAttribute.cs b/src/Umbraco.Web/WebApi/Filters/FilterAllowedOutgoingContentAttribute.cs
index 8193b528f6..354313517e 100644
--- a/src/Umbraco.Web/WebApi/Filters/FilterAllowedOutgoingContentAttribute.cs
+++ b/src/Umbraco.Web/WebApi/Filters/FilterAllowedOutgoingContentAttribute.cs
@@ -57,7 +57,7 @@ namespace Umbraco.Web.WebApi.Filters
var toRemove = new List();
foreach(dynamic item in items)
{
- var nodePermission = permissions.Where(x => x.EntityId == item.Id).ToArray();
+ var nodePermission = permissions.Where(x => x.EntityId == Convert.ToInt32(item.Id)).ToArray();
//if there are no permissions for this id then we need to check what the user's default
// permissions are.
if (nodePermission.Any() == false)