London Dev Meetup Rescheduled! Due to unavoidable reasons, the event has been moved to 21st May. Speakers remain the same—any changes will be communicated. Seats are limited—register here to secure your spot!

[Ignore]-property loses value after IIS reset

Vote:
0

I have a Block type that allows nested blocks for structuring block layouts.

[ContentType(DisplayName = "Row Layout Block")]
public class RowLayoutBlock : BlockData
{

    [Display(Name = "Blocks")]
    [AllowedTypes(typeof(IRowLayoutItemBlock))]
    public virtual ContentArea Items { get; set; }

}

IRowLayoutItemBlock contains a flag that tells the front-end that this block should be handled a little bit differently.

public interface IRowLayoutItemBlock : IContentData
{
    bool IsRowLayoutItem { get; set; }
}

I don't want this flag to be visible/editable in the CMS editor and I've added the [Ignore] attribute on the inherited member.

[ContentType(DisplayName = "Image Block")]
public class ImageBlock : BlockData, IRowLayoutItemBlock
{
    [Ignore]
    public virtual bool IsRowLayoutItem { get; set; }
}

To set this flag I've subscribed an event handler on SavingContent and CreatingContent

context.ConfigurationComplete += delegate
{
    var contentEvents = context.StructureMap().GetInstance<IContentEvents>();

    contentEvents.SavingContent += (sender, args) => RowLayoutBlockContentEventListener.SetIsRowLayoutItemOnItems(args);
    contentEvents.CreatingContent += (sender, args) => RowLayoutBlockContentEventListener.SetIsRowLayoutItemOnItems(args);
};
public class RowLayoutBlockContentEventListener
{
    public static void SetIsRowLayoutItemOnItems(ContentEventArgs args)
    {
        if(args.Content is RowLayoutBlock rowLayoutBlock && rowLayoutBlock.Items?.Items != null)
        {
            var contentRepository = ServiceLocator.Current.GetInstance<IContentRepository>();
            foreach (var item in rowLayoutBlock.Items.Items)
            {
                if (contentRepository.TryGet<IRowLayoutItemBlock>(item.ContentLink, out var rowLayoutItem))
                {
                    rowLayoutItem.IsRowLayoutItem = true;
                }
            }
        }
    }
}

This all work perfectly until I do a restart of IIS when all the flags are unset/set to false for some reason.

Is there a better way to do this or am I just missing something?

#219152
Edited, Mar 30, 2020 11:05
Vote:
1

Try the [ScaffoldColumn(false)] or the [Editable(false)] attributes instead.

Avoid using Ignore attribute on blocks or pages. "here be dragons".

Ignored properties are not really stored by Episerver in the background. They use a static class to store them so it will be wiped when IIS reset etc. Using load balancing and this can cause some serious headaches. So stay away from that one.

#219154
Edited, Mar 30, 2020 11:17
Vote:
0

I don't want to use [Editable(false)] because I want it to be hidden not just "disabled".

If I use [ScaffoldColumn(false)] I get an error "NotSupportedException: The property IsRowLayoutItem is read-only" in RowLayoutBlockContentEventListener on rowLayoutItem.IsRowLayoutItem = true

EDIT: Fixed it with a writable clone and a bunch of ugly casts. Seems to work, thanks!

private static void SetIsRowLayoutItemOnItems(ContentEventArgs args)
{
    if(args.Content is RowLayoutBlock rowLayoutBlock && rowLayoutBlock.Items?.Items != null)
    {
        var contentRepository = ServiceLocator.Current.GetInstance<IContentRepository>();
        foreach (var item in rowLayoutBlock.Items.Items)
        {
            if (contentRepository.TryGet<IRowLayoutItemBlock>(item.ContentLink, out var rowLayoutItem))
            {
                var content = (IContent)((IReadOnly)rowLayoutItem).CreateWritableClone();
                ((IRowLayoutItemBlock)content).IsRowLayoutItemBlock = true;
                contentRepository.Save(content, SaveAction.Publish | SaveAction.ForceCurrentVersion, AccessLevel.NoAccess);
            }
        }
    }
}
#219158
Edited, Mar 30, 2020 11:51
Vote:
0

If you want to disable the property, or show is as read-only, you could use this attribute:

[Editable(false)]
#219193
Mar 31, 2020 6:06
This topic was created over six months ago and has been resolved. If you have a similar question, please create a new topic and refer to this one.
* 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.