public virtual IHttpActionResult CreateContent(string ParentRef, string ContentType, [FromBody] ExpandoObject content, EPiServer.DataAccess.SaveAction action = EPiServer.DataAccess.SaveAction.Save)
        {
            //Instantiate content of named type
            var p = LookupRef(ParentRef);

            if (p == ContentReference.EmptyReference)
            {
                return(NotFound());
            }
            int j = 0;

            var ctype = _typerepo.Load(ContentType);

            if (ctype == null && int.TryParse(ContentType, out j))
            {
                ctype = _typerepo.Load(j);
            }
            if (ctype == null)
            {
                return(NotFound());
            }


            var properties = content as IDictionary <string, object>;

            IContent con = _repo.GetDefault <IContent>(p, ctype.ID);

            UpdateContentWithProperties(properties, con);
            //TODO: Handle local blocks. Handle properties that are not strings (parse values).

            if (properties.ContainsKey("Name"))
            {
                con.Name = properties["Name"].ToString();
            }
            EPiServer.DataAccess.SaveAction saveaction = action;
            if (properties.ContainsKey("SaveAction") && properties["SaveAction"] == "Publish")
            {
                saveaction = EPiServer.DataAccess.SaveAction.Publish;
            }
            var rt = _repo.Save(con, saveaction);

            return(Created <object>(new Uri(Url.Link("GetContentRoute", new { Reference = rt.ToReferenceWithoutVersion().ToString() })), new { reference = rt.ToReferenceWithoutVersion().ToString() }));
        }
        public virtual IHttpActionResult PutContent(string Reference, [FromBody] ExpandoObject Updated, EPiServer.DataAccess.SaveAction action = EPiServer.DataAccess.SaveAction.Save)
        {
            var r = LookupRef(Reference);

            if (r == ContentReference.EmptyReference)
            {
                return(NotFound());
            }
            var content = (_repo.Get <IContent>(r) as IReadOnly).CreateWritableClone() as IContent;
            var dic     = Updated as IDictionary <string, object>;

            UpdateContentWithProperties(dic, content);
            EPiServer.DataAccess.SaveAction saveaction = action;
            if (dic.ContainsKey("SaveAction") && ((string)dic["SaveAction"]) == "Publish")
            {
                saveaction = EPiServer.DataAccess.SaveAction.Publish;
            }
            var rt = _repo.Save(content, saveaction);

            return(Ok(new { reference = rt.ToString() }));
        }
        public virtual IHttpActionResult UpdateContent(string Path, [FromBody] ExpandoObject Updated, EPiServer.DataAccess.SaveAction action = EPiServer.DataAccess.SaveAction.Save)
        {
            Path = Path ?? "";
            var r = FindContentReference(Path);

            if (r == ContentReference.EmptyReference)
            {
                return(NotFound());
            }
            if (r == ContentReference.RootPage)
            {
                return(BadRequest("Cannot update Root entity"));
            }

            var content = (_repo.Get <IContent>(r) as IReadOnly).CreateWritableClone() as IContent;
            var dic     = Updated as IDictionary <string, object>;

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

            // Store the new information in the object.
            UpdateContentWithProperties(dic, content, out string error);
            if (!string.IsNullOrEmpty(error))
            {
                return(BadRequest($"Invalid property '{error}'"));
            }

            // Save the reference and publish if requested.
            var rt = _repo.Save(content, saveaction);

            return(Ok(new { reference = rt.ToString() }));
        }
        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;
            }
        }
 public SaveContentCommand(IContentRepository contentRepository)
 {
     _repo  = contentRepository;
     Action = EPiServer.DataAccess.SaveAction.Publish;
 }
        public virtual IHttpActionResult CreateContent(string Path, [FromBody] ExpandoObject content, EPiServer.DataAccess.SaveAction action = EPiServer.DataAccess.SaveAction.Save)
        {
            Path = Path ?? "";
            var r = FindContentReference(Path);

            if (r == ContentReference.EmptyReference)
            {
                return(NotFound());
            }

            // Instantiate content of named type.
            var properties = content as IDictionary <string, object>;

            if (properties == null || !properties.TryGetValue("ContentType", out object ContentType))
            {
                return(BadRequest("'ContentType' is a required field."));
            }

            // Check ContentType.
            var ctype = _typerepo.Load((string)ContentType);

            if (ctype == null && int.TryParse((string)ContentType, out int j))
            {
                ctype = _typerepo.Load(j);
            }
            if (ctype == null)
            {
                return(BadRequest($"'{ContentType}' is an invalid ContentType"));
            }

            // Remove 'ContentType' from properties before iterating properties.
            properties.Remove("ContentType");

            // Check if the object already exists.
            if (properties.TryGetValue("Name", out object name))
            {
                var temp = _repo.GetChildren <IContent>(r).Where(ch => ch.Name == (string)name).FirstOrDefault();
                if (temp != null)
                {
                    return(BadRequest($"Content with name '{name}' already exists"));
                }
            }

            // Create content.
            IContent con = _repo.GetDefault <IContent>(r, ctype.ID);

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

            // Set the reference name.
            string _name = "";

            if (properties.ContainsKey("Name"))
            {
                _name = properties["Name"].ToString();
                properties.Remove("Name");
            }

            if (!string.IsNullOrEmpty(_name))
            {
                con.Name = _name;
            }

            // Set all the other values.
            UpdateContentWithProperties(properties, con, out string error);
            if (!string.IsNullOrEmpty(error))
            {
                return(BadRequest($"Invalid property '{error}'"));
            }

            // Save the reference with the requested save action.
            if (!string.IsNullOrEmpty(_name))
            {
                con.Name = _name;
            }
            try
            {
                var rt = _repo.Save(con, saveaction);
                return(Created <object>(Path, new { reference = rt.ID }));
            } catch (ValidationException ex)
            {
                return(BadRequest(ex.Message));
            }
        }