public virtual IHttpActionResult CreateContent(string path, [FromBody] Dictionary <string, object> contentProperties, EPiServer.DataAccess.SaveAction action = EPiServer.DataAccess.SaveAction.Save)
        {
            path = path ?? "";
            var parentContentRef = FindContentReference(path);

            if (parentContentRef == ContentReference.EmptyReference)
            {
                return(NotFound());
            }
            if (!ReferenceExists(parentContentRef))
            {
                return(NotFound());
            }

            // Instantiate content of named type.
            if (contentProperties == null)
            {
                return(BadRequestErrorCode("BODY_EMPTY"));
            }

            foreach (String property in NonCreatingProperties)
            {
                if (contentProperties.ContainsKey(property))
                {
                    contentProperties.Remove(property);
                }
            }
            object contentTypeString;

            if (!(contentProperties.TryGetValue("ContentType", out contentTypeString) || contentProperties.TryGetValue("__EpiserverContentType", out contentTypeString)))
            {
                return(BadRequestValidationErrors(ValidationError.Required("ContentType")));
            }

            if (contentProperties.ContainsKey("ContentType"))
            {
                contentProperties.Remove("ContentType");
            }

            if (contentProperties.ContainsKey("__EpiserverContentType"))
            {
                contentProperties.Remove("__EpiserverContentType");
            }

            if (!(contentTypeString is string))
            {
                return(BadRequestValidationErrors(ValidationError.InvalidType("ContentType", typeof(string))));
            }

            // Check ContentType.
            ContentType contentType = FindEpiserverContentType(contentTypeString);

            if (contentType == null)
            {
                return(BadRequestValidationErrors(ValidationError.CustomError("ContentType", "CONTENT_TYPE_INVALID", $"Could not find contentType {contentTypeString}")));
            }

            if (!contentProperties.TryGetValue("Name", out object nameValue))
            {
                return(BadRequestValidationErrors(ValidationError.Required("Name")));
            }
            contentProperties.Remove("Name");

            if (!(nameValue is string))
            {
                return(BadRequestValidationErrors(ValidationError.InvalidType("Name", typeof(string))));
            }

            EPiServer.DataAccess.SaveAction saveaction = action;
            if (contentProperties.ContainsKey("SaveAction") && (string)contentProperties["SaveAction"] == "Publish")
            {
                saveaction = EPiServer.DataAccess.SaveAction.Publish;
                contentProperties.Remove("SaveAction");
            }
            if (contentProperties.ContainsKey("SaveAction") && (string)contentProperties["SaveAction"] == "RequestApproval")
            {
                saveaction = EPiServer.DataAccess.SaveAction.RequestApproval;
                contentProperties.Remove("SaveAction");
            }
            if (contentProperties.ContainsKey("SaveAction") && ((string)contentProperties["SaveAction"]) == "CheckIn")
            {
                saveaction = EPiServer.DataAccess.SaveAction.CheckIn;
                contentProperties.Remove("SaveAction");
            }

            // Create content.
            IContent content;

            CultureInfo cultureInfo = null;

            // Check if a Language tag is set.
            if (contentProperties.TryGetValue("__EpiserverCurrentLanguage", out object languageValue))
            {
                if (!(languageValue is string))
                {
                    return(BadRequestValidationErrors(ValidationError.InvalidType("__EpiserverCurrentLanguage", typeof(string))));
                }

                if (!TryGetCultureInfo((string)languageValue, out cultureInfo))
                {
                    if (cultureInfo == null || !GetLanguages().Any(ci => ci.TwoLetterISOLanguageName == cultureInfo.TwoLetterISOLanguageName))
                    {
                        return(BadRequestInvalidLanguage(languageValue.ToString()));
                    }
                    cultureInfo = new CultureInfo(cultureInfo.TwoLetterISOLanguageName);
                }

                if (!GetLanguages().Any(ci => ci.TwoLetterISOLanguageName == cultureInfo.TwoLetterISOLanguageName))
                {
                    return(BadRequestInvalidLanguage(languageValue.ToString()));
                }
                cultureInfo = new CultureInfo(cultureInfo.TwoLetterISOLanguageName);


                if (_repo.TryGet <IContent>(parentContentRef, cultureInfo, out IContent parent))
                {
                    return(BadRequestLanguageBranchExists(parent, cultureInfo.TwoLetterISOLanguageName));
                }

                content = _repo.CreateLanguageBranch <IContent>(parentContentRef, cultureInfo);
            }
            else
            {
                content = _repo.GetDefault <IContent>(parentContentRef, contentType.ID);
            }
            if (contentProperties.ContainsKey("__EpiserverCurrentLanguage"))
            {
                contentProperties.Remove("__EpiserverCurrentLanguage");
            }

            content.Name = (string)nameValue;

            // Set all the other values.
            var errors = UpdateContentProperties(contentProperties, content);

            if (errors.Any())
            {
                return(BadRequestValidationErrors(errors.ToArray()));
            }

            var validationErrors = _validationService.Validate(content);

            if (validationErrors.Any())
            {
                return(BadRequestValidationErrors(validationErrors.Select(ValidationError.FromEpiserver).ToArray()));
            }

            // Save the reference with the requested save action.
            try
            {
                var createdReference = _repo.Save(content, saveaction);
                if (TryGetProject(out int projectId, out Project project))
                {
                    ProjectItem projectItem = new ProjectItem(projectId, content);
                    _projectrepo.SaveItems(new ProjectItem[] { projectItem });
                }
                return(Created(path, new { reference = createdReference.ID, __EpiserverCurrentLanguage = cultureInfo }));
            }
            catch (AccessDeniedException)
            {
                return(StatusCode(HttpStatusCode.Forbidden));
            }
            catch (EPiServerException)
            {
                return(BadRequestValidationErrors(ValidationError.TypeCannotBeUsed("ContentType", contentType.Name, _repo.Get <IContent>(parentContentRef).GetOriginalType().Name)));
            }
        }
        public virtual IHttpActionResult UpdateContent(string path, [FromBody] Dictionary <string, object> newProperties, EPiServer.DataAccess.SaveAction action = EPiServer.DataAccess.SaveAction.Save)
        {
            path = path ?? "";
            var contentRef = FindContentReference(path);

            if (contentRef == ContentReference.EmptyReference)
            {
                return(NotFound());
            }
            if (contentRef == ContentReference.RootPage)
            {
                return(BadRequestErrorCode("UPDATE_ROOT_NOT_ALLOWED"));
            }

            if (!TryGetCultureInfo(out string language, out CultureInfo cultureInfo))
            {
                return(BadRequestInvalidLanguage(language));
            }

            if (!_repo.TryGet(contentRef, cultureInfo, out IContent originalContent))
            {
                return(NotFound());
            }

            if (newProperties == null)
            {
                return(BadRequestErrorCode("BODY_EMPTY"));
            }

            foreach (String property in NonCreatingProperties)
            {
                if (newProperties.ContainsKey(property))
                {
                    newProperties.Remove(property);
                }
            }

            foreach (String property in NonUpdatingProperties)
            {
                if (newProperties.ContainsKey(property))
                {
                    newProperties.Remove(property);
                }
            }

            var content = (originalContent as IReadOnly).CreateWritableClone() as IContent;

            EPiServer.DataAccess.SaveAction saveaction = action;
            if (newProperties.ContainsKey("SaveAction") && ((string)newProperties["SaveAction"]) == "Publish")
            {
                saveaction = EPiServer.DataAccess.SaveAction.Publish;
                newProperties.Remove("SaveAction");
            }
            if (newProperties.ContainsKey("SaveAction") && ((string)newProperties["SaveAction"]) == "RequestApproval")
            {
                saveaction = EPiServer.DataAccess.SaveAction.RequestApproval;
                newProperties.Remove("SaveAction");
            }
            if (newProperties.ContainsKey("SaveAction") && ((string)newProperties["SaveAction"]) == "CheckIn")
            {
                saveaction = EPiServer.DataAccess.SaveAction.CheckIn;
                newProperties.Remove("SaveAction");
            }

            IContent moveTo = null;

            if (newProperties.ContainsKey(MoveEntityToPropertyKey))
            {
                if (!(newProperties[MoveEntityToPropertyKey] is string))
                {
                    return(BadRequestValidationErrors(ValidationError.InvalidType(MoveEntityToPropertyKey, typeof(string))));
                }

                var moveToPath = (string)newProperties[MoveEntityToPropertyKey];
                if (!moveToPath.StartsWith("/"))
                {
                    return(BadRequestValidationErrors(ValidationError.CustomError(MoveEntityToPropertyKey, "FIELD_INVALID_FORMAT", $"{MoveEntityToPropertyKey} should start with a /")));
                }

                if (!_repo.TryGet(FindContentReference(moveToPath.Substring(1)), out moveTo))
                {
                    return(BadRequestValidationErrors(ValidationError.CustomError(MoveEntityToPropertyKey, "TARGET_CONTAINER_NOT_FOUND", "The target container was not found")));
                }

                newProperties.Remove(MoveEntityToPropertyKey);
            }

            if (newProperties.ContainsKey("Name"))
            {
                content.Name = newProperties["Name"].ToString();
                newProperties.Remove("Name");
            }

            // Store the new information in the object.
            var errors = UpdateContentProperties(newProperties, content);

            if (errors.Any())
            {
                return(BadRequestValidationErrors(errors.ToArray()));
            }

            var validationErrors = _validationService.Validate(content);

            if (validationErrors.Any())
            {
                return(BadRequestValidationErrors(validationErrors.Select(ValidationError.FromEpiserver).ToArray()));
            }

            if (!HasAccess(content, EPiServer.Security.AccessLevel.Edit | EPiServer.Security.AccessLevel.Publish))
            {
                return(StatusCode(HttpStatusCode.Forbidden));
            }

            if (moveTo != null)
            {
                if (!HasAccess(content, EPiServer.Security.AccessLevel.Read | EPiServer.Security.AccessLevel.Delete))
                {
                    return(StatusCode(HttpStatusCode.Forbidden));
                }

                if (!HasAccess(moveTo, EPiServer.Security.AccessLevel.Create | EPiServer.Security.AccessLevel.Publish))
                {
                    return(StatusCode(HttpStatusCode.Forbidden));
                }
            }

            //from here on we're going to try to save things to the database, we have tried to optimize the chance of succeeding above

            if (moveTo != null)
            {
                try
                {
                    _repo.Move(contentRef, moveTo.ContentLink);
                }
                catch (ContentNotFoundException)
                {
                    //even though we already check for this above, we still handle it here for cases that we might not have foreseen
                    return(BadRequestValidationErrors(ValidationError.CustomError(MoveEntityToPropertyKey, "TARGET_CONTAINER_NOT_FOUND", "The target container was not found")));
                }
                catch (AccessDeniedException)
                {
                    //even though we already check for this above, we still handle it here for cases that we might not have foreseen
                    return(StatusCode(HttpStatusCode.Forbidden));
                }
            }

            try
            {
                var updatedReference = _repo.Save(content, saveaction);
                if (TryGetProject(out int projectId, out Project project))
                {
                    ProjectItem projectItem = new ProjectItem(projectId, content);
                    _projectrepo.SaveItems(new ProjectItem[] { projectItem });
                }
                return(Ok(new { reference = updatedReference.ToString() }));
            }
            catch (Exception)
            {
                if (moveTo != null)
                {
                    //try to undo the move. We've tried using TransactionScope for this, but it doesn't play well with Episerver (caching, among other problems)
                    _repo.Move(contentRef, originalContent.ParentLink);
                }
                throw;
            }
        }