volume_up

A critical vulnerability was discovered in React Server Components (Next.js). Our systems remain protected but we advise to update packages to newest version. Learn More

AI OnAI Off

LinkItem and PropertyList

I'm trying to add a LinkItem property to a PropertyList type (I can't use LinkItemCollection as I need more properties on each item), but this fails during block creation and results in a stack overflow (stack trace can be found further below).

I've set up a basic example in a new Alloy project on the latest CMS version (12.22.4), and the block type looks like this:

[ContentType(DisplayName = "Example block", GUID = "de1b6876-c408-4283-a748-6ede69cd860b")]
public class ExampleBlock : BlockData
{
    [EditorDescriptor(EditorDescriptorType = typeof(CollectionEditorDescriptor<ExampleListItem>))]
    public virtual IList<ExampleListItem> Items { get; set; }
}

And the item type looks like this:

public class ExampleListItem
{
    public LinkItem Link { get; set; }
}

I've also set up a basic property definition for this (empty class inheriting PropertyList<ExampleListItem>).

This setup fails instantly once you create a new block in a content area and select the ExampleBlock type.

I've also tried decorating the LinkItem property with [JsonConverter(typeof(SystemTextLinkItemConverter))] (using the System.Text.Json.Serialization namespace for the attribute), as I believe Url properties require the same approach in PropertyLists, but this does not help in this case.

Is there anything I'm missing here, or a possible workaround to get this to work?

Part of the stack trace (last few rows keep piling up):

Stack overflow.
   at System.Reflection.RuntimeAssembly.GetCodeBase(System.Runtime.CompilerServices.QCallAssembly, System.Runtime.CompilerServices.StringHandleOnStack)
   at System.Reflection.RuntimeAssembly.GetCodeBase()
   at System.Reflection.RuntimeAssembly.GetName(Boolean)
   at EPiServer.Shell.ObjectEditing.Internal.TypeSerializer.GetAssemblyTypeNameWithoutVersion(System.Type)
   at EPiServer.Shell.ObjectEditing.Internal.EditorDefinitionRepository.GetEditorDefinitionDDSO(System.Type, System.String)
   at EPiServer.Shell.ObjectEditing.Internal.EditorDefinitionRepository.Get(System.Type, System.String)
   at EPiServer.Shell.ObjectEditing.MetadataHandlerRegistry.GetMetadataHandlers(System.Type, System.String)
   at EPiServer.Shell.ObjectEditing.ExtensibleMetadataProvider.GetExtendedMetadata(System.Collections.Generic.IEnumerable`1<System.Attribute>, System.Type, System.Func`1<System.Object>, System.Type, System.String)
   at EPiServer.Shell.ObjectEditing.ExtendedMetadata.<get_Properties>b__37_0(Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata)
   at System.Linq.Enumerable+SelectIListIterator`2[[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].ToArray()
   at EPiServer.Shell.ObjectEditing.ExtendedMetadata.get_Properties()
   at EPiServer.Shell.UI.Rest.DefaultMetadataStoreModelCreator.ExtractMetadataFromProperties(EPiServer.Shell.ObjectEditing.ExtendedMetadata, EPiServer.Shell.UI.Models.MetadataStoreModel, EPiServer.Framework.Localization.LocalizationService, EPiServer.Shell.UIDescriptorRegistry, EPiServer.Shell.ObjectEditing.ISelectionFactory[])
   at EPiServer.Shell.UI.Rest.DefaultMetadataStoreModelCreator.CreateFromModelMetadata(EPiServer.Shell.ObjectEditing.ExtendedMetadata, EPiServer.Framework.Localization.LocalizationService, EPiServer.Shell.UIDescriptorRegistry, EPiServer.Shell.ObjectEditing.ISelectionFactory[], Boolean)
   at EPiServer.Shell.UI.Rest.DefaultMetadataStoreModelCreator.ExtractMetadataFromProperties(EPiServer.Shell.ObjectEditing.ExtendedMetadata, EPiServer.Shell.UI.Models.MetadataStoreModel, EPiServer.Framework.Localization.LocalizationService, EPiServer.Shell.UIDescriptorRegistry, EPiServer.Shell.ObjectEditing.ISelectionFactory[])
   at EPiServer.Shell.UI.Rest.DefaultMetadataStoreModelCreator.CreateFromModelMetadata(EPiServer.Shell.ObjectEditing.ExtendedMetadata, EPiServer.Framework.Localization.LocalizationService, EPiServer.Shell.UIDescriptorRegistry, EPiServer.Shell.ObjectEditing.ISelectionFactory[], Boolean)
   at EPiServer.Shell.UI.Rest.DefaultMetadataStoreModelCreator.ExtractMetadataFromProperties(EPiServer.Shell.ObjectEditing.ExtendedMetadata, EPiServer.Shell.UI.Models.MetadataStoreModel, EPiServer.Framework.Localization.LocalizationService, EPiServer.Shell.UIDescriptorRegistry, EPiServer.Shell.ObjectEditing.ISelectionFactory[])
   at EPiServer.Shell.UI.Rest.DefaultMetadataStoreModelCreator.CreateFromModelMetadata(EPiServer.Shell.ObjectEditing.ExtendedMetadata, EPiServer.Framework.Localization.LocalizationService, EPiServer.Shell.UIDescriptorRegistry, EPiServer.Shell.ObjectEditing.ISelectionFactory[], Boolean)
   at EPiServer.Shell.UI.Rest.DefaultMetadataStoreModelCreator.ExtractMetadataFromProperties(EPiServer.Shell.ObjectEditing.ExtendedMetadata, EPiServer.Shell.UI.Models.MetadataStoreModel, EPiServer.Framework.Localization.LocalizationService, EPiServer.Shell.UIDescriptorRegistry, EPiServer.Shell.ObjectEditing.ISelectionFactory[])
   at EPiServer.Shell.UI.Rest.DefaultMetadataStoreModelCreator.CreateFromModelMetadata(EPiServer.Shell.ObjectEditing.ExtendedMetadata, EPiServer.Framework.Localization.LocalizationService, EPiServer.Shell.UIDescriptorRegistry, EPiServer.Shell.ObjectEditing.ISelectionFactory[], Boolean)
#307463
Aug 25, 2023 11:05

I would remove [EditorDescriptor(EditorDescriptorType = typeof(CollectionEditorDescriptor<ExampleListItem>))] and have ExampleListItem inherit from block data.  I think the issues is you mising new inline blocks and old property list

#307466
Aug 25, 2023 21:20
Ted

Hi Mark! We have a lot of block types with IList<T> properties where T is a POCO type.

We're not using IList<T> where T is a block type in this case, so I don't think we're mixing the two (let me know if I misunderstood what you meant).

This exact setup works if the Link property is, for example, of type ContentReference.

So I think this should work, but there seems to be a bug related to serialization?

Or is Optimizely officially removing the support for POCO types, forcing all IList item types (except value types) to in fact be block types going forward?

#307577
Edited, Aug 28, 2023 8:22

Not answering the question directly, but maybe you can be interested in Geta Generic Links - they try to solve need similar to what you/ve described https://www.getadigital.com/no/blogg/extending-link-item-collections

There can be some issues with Content Management API though (thats how I stumbled on that package) so be warned.

#307578
Aug 28, 2023 12:15
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.