Try our conversational search powered by Generative AI!

Can't send content to review

Fixed in

EPiServer.CMS.UI 11.14.1

(Or a related package)

Created

Dec 27, 2018

Updated

Oct 21, 2019

Area

CMS UI

State

Closed, Fixed and tested


Description

Steps to reproduce:

  1. Define a block type from the sample code below.
  2. For "For All Sites," set up an approval sequence where the logged in user is a reviewer.
  3. Create an Accordion block.
  4. Add a new item to the Property List.
  5. Send content to review.
  6. Approve.
  7. Publish.
  8. Edit a row of the Property List.
  9. Send content to review.

Expected:
No problem

Actual:
An exception: "Content is locked by 'alfred' with lock identifier 'contentapproval'"

Note: To reproduce again, create a new block.

using System.Collections;
using System.ComponentModel.DataAnnotations;
using EPiServer.Core;
using EPiServer.DataAbstraction;
using EPiServer.DataAnnotations;
using EPiServer.SpecializedProperties;
using AlloyTemplates.Models.Blocks;
using EPiServer.Cms.Shell.UI.ObjectEditing.EditorDescriptors;
using EPiServer.Shell.ObjectEditing;
using System.Collections.Generic;
using EPiServer.Framework.Serialization;
using EPiServer.Framework.Serialization.Internal;
using EPiServer.PlugIn;
using EPiServer.ServiceLocation;
 
namespace AlloyTemplates.Models.Pages
{
    /// <summary>
    /// Used for the site's start page and also acts as a container for site settings
    /// </summary>
    [ContentType(
        GUID = "19671657-B684-4D95-A61F-8DD4FE60D559",
        GroupName = Global.GroupNames.Specialized)]
    [SiteImageUrl]
    [AvailableContentTypes(
        Availability.Specific,
        Include = new[] { typeof(ContainerPage), typeof(ProductPage), typeof(StandardPage), typeof(ISearchPage), typeof(LandingPage), typeof(ContentFolder) }, // Pages we can create under the start page...
        ExcludeOn = new[] { typeof(ContainerPage), typeof(ProductPage), typeof(StandardPage), typeof(ISearchPage), typeof(LandingPage) })] // ...and underneath those we can't create additional start pages
    public class StartPage : SitePageData
    {
        [Display(
            GroupName = SystemTabNames.Content,
            Order = 320)]
        [CultureSpecific]
        public virtual ContentArea MainContentArea { get; set; }
 
        [Display(GroupName = Global.GroupNames.SiteSettings, Order = 300)]
        public virtual LinkItemCollection ProductPageLinks { get; set; }
 
        [Display(GroupName = Global.GroupNames.SiteSettings, Order = 350)]
        public virtual LinkItemCollection CompanyInformationPageLinks { get; set; }
 
        [Display(GroupName = Global.GroupNames.SiteSettings, Order = 400)]
        public virtual LinkItemCollection NewsPageLinks { get; set; }
 
        [Display(GroupName = Global.GroupNames.SiteSettings, Order = 450)]
        public virtual LinkItemCollection CustomerZonePageLinks { get; set; }
 
        [Display(GroupName = Global.GroupNames.SiteSettings)]
        public virtual PageReference GlobalNewsPageLink { get; set; }
 
        [Display(GroupName = Global.GroupNames.SiteSettings)]
        public virtual PageReference ContactsPageLink { get; set; }
 
        [Display(GroupName = Global.GroupNames.SiteSettings)]
        public virtual PageReference SearchPageLink { get; set; }
 
        [Display(GroupName = Global.GroupNames.SiteSettings)]
        public virtual SiteLogotypeBlock SiteLogotype { get; set; }
 
    }
 
 
    [ContentType(DisplayName = "Accordion Block", GUID = "dc8b8f32-ffba-48b5-8902-47a2b0ef9b77", Description = "Allows you to create expandable accordion content and display it in three different ways.", GroupName = "Page Components")]
    [SiteImageUrl]
    public class AccordionBlockData : BlockData
    {
        [CultureSpecific]
        [Display(Name = "Accordion Panels", Order = 30)]
        [EditorDescriptor(EditorDescriptorType = typeof(CollectionEditorDescriptor<Accordion>))]
        public virtual IList<Accordion> Rows { get; set; }
    }
 
    public class Accordion
    {
        [Required]
        public virtual string Header { get; set; }
    }
 
    [PropertyDefinitionTypePlugIn]
    public class AccordionProperty : PropertyListBase<Accordion> { }
 
    public class PropertyListBase<T> : PropertyList<T>
    {
        protected Injected<ObjectSerializerFactory> ObjectSerializerFactory { get; set; }
        private readonly IObjectSerializer _objectSerializer;
 
        public PropertyListBase()
        {
            _objectSerializer = ObjectSerializerFactory.Service.GetSerializer("application/json");
        }
 
        protected override T ParseItem(string value)
        {
            return _objectSerializer.Deserialize<T>(value);
        }
    }
}