Restrict Blocks in ContentArea

Vote:
 

I'm having a issue restricting what kind of Block to be inserted in a ContentArea. What I want is that the SliderBlock's ContentArea property can only have insertion of a SlideItemBlock.

My block classes:

[ContentType(...)]
public class SlideItemBlock : BlockData
{
	[Required]
	Display(Name = "Image")]
	public virtual string Image { get; set;}
}

[ContentType(...)]
public class SliderBlock : BlockData
{
	[Required]
	[Display(Name = "Slides")]
	public virtual ContentArea Slides { get; set; }
	//Should only accept insertion of SlideItemBlock
}

    

Or is this the wrong way to achive what I'm trying to restrict for the editor to not drag and drop wrong block types?

As of now, I can create a SliderBlock and insert a SlideItemBlocks in it. If I then insert the created SliderBlock in a new SliderBlock I get a forever and ever loop and It breaks the site. This is what I'm trying to control.

#77678
Nov 22, 2013 14:30
Vote:
 

What you could very easily do is to implement IValidator class that will be triggered when a page/block is saved.

See the following example, but you might use any condition you like:

    public class CarouselContentValidator : IValidate<StartPage>
    {
        IEnumerable<ValidationError> IValidate<StartPage>.Validate(StartPage instance)
        {
            if (instance.CarouselContent.AnyBlocks())
            {
                if (instance.CarouselContent.Contents.Any(
                    c => !c.GetOriginalType().IsAssignableFrom(typeof(TextOverImageBlock)))) 
                {
                    var validationError = new ValidationError
                    {
                        ErrorMessage = LocalizationService.Current.GetString("/validation/carouselblocks"),
                        PropertyName = "CarouselContent"
                    };

                    return new[] { validationError };
                }
            }


            return Enumerable.Empty<ValidationError>();
        }
    }

    

#77681
Nov 22, 2013 15:02
Vote:
 

I get an error for GetOriginalType(). It says EPiServer.Core.IContent does not contain a definition for this. How can I fix this?

#77682
Nov 22, 2013 15:32
Vote:
 

Hmm, that's strange, for me it works like charm, let me think about it...

#77683
Nov 22, 2013 15:37
Vote:
 

You can also implement ValidationAttribute (http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.validationattribute(v=vs.110).aspx) to handle the validation directly in the attribute whereever it's used. We will have a built in attribute to handle this in the 7.5 release.

#77688
Nov 22, 2013 17:44
Vote:
 

I found this on nuget and it solves all of my problem with ContentAreas restrictions.

http://www.nuget.org/packages/OpenWaves.EPiServer.ExtendedContentAreaEditor/

#77863
Edited, Nov 27, 2013 12:37
Vote:
 

"I get an error for GetOriginalType(). It says EPiServer.Core.IContent does not contain a definition for this. How can I fix this?"


I recently had the same problem after updating Episerver from the oldest possible version 7 to the latest.  The solution was to add a "using EpiServer;" reference to the top of the document, as the method is an extension defined in EPiServer.RuntimeModelExtensions. I have no idea why the reference wasn't needed on the old codebase, but adding it after the update made it work again.

#79343
Dec 13, 2013 13:51
Vote:
 

Ripped From the AvailablePageTypes type attribute:

 

[AttributeUsage(AttributeTargets.Property)]
public class AvailableContentTypesAttribute : ValidationAttribute
{
    public System.Type[] Include
    {
        get;
        set;
    }
    public System.Type[] Exclude
    {
        get;
        set;
    }

    public override bool IsValid(object value)
    {
        if ((value != null) && !(value is ContentArea))
        {
            throw new ValidationException("AvailableContentTypesAttribute is intended only for use with ContentArea properties");
        }

        var contentArea = value as ContentArea;

        var notAllowedcontentNames = new List<string>();

        if (contentArea != null)
        {
            if (Include != null)
            {
                var notAllowedContent = contentArea.Contents.Where(x => !ContainsType(Include, x.GetType()));
                if (notAllowedContent.Any())
                {
                    notAllowedcontentNames.AddRange(notAllowedContent.Select(x => string.Format("{0} ({1})", x.Name, x.ContentLink.ID)));
                }
            }
            if (Exclude != null)
            {
                var notAllowedContent = contentArea.Contents.Where(x => ContainsType(Exclude, x.GetType()));
                if (notAllowedContent.Any())
                {
                    notAllowedcontentNames.AddRange(notAllowedContent.Select(x => string.Format("{0} ({1})", x.Name, x.ContentLink.ID)));
                }
            }
        }

        if (notAllowedcontentNames.Any())
        {
            ErrorMessage = "contains invalid content items :";
            foreach (var notAllowedcontentName in notAllowedcontentNames)
            {
                ErrorMessage += " " + notAllowedcontentName + ",";
            }
            ErrorMessage = ErrorMessage.TrimEnd(',');

            return false;
        }
        return true;
    }

    private bool ContainsType(Type[] include, Type type)
    {
        return include.Any(inc => inc.IsAssignableFrom(type));
    }

    protected override System.ComponentModel.DataAnnotations.ValidationResult IsValid(object value, System.ComponentModel.DataAnnotations.ValidationContext validationContext)
    {
        var result = base.IsValid(value, validationContext);
        if (result != null && !string.IsNullOrEmpty(result.ErrorMessage))
        {
            result.ErrorMessage = string.Format("{0} {1}", validationContext.DisplayName, ErrorMessage);
        }
        return result;
    }
}

    

Usage:

Explicit inclusion:

[AvailableContentTypes(Include = new[] { typeof(SomeBlockType), typeof(SomePageType) })]
public virtual ContentArea ContentAreaProperty { get; set; }
 

Explicit exclusion:

[AvailableContentTypes(Exclude = new[] { typeof(NoAllowedBlockType), typeof(NotAllowedPageType) })]
public virtual ContentArea ContentAreaProperty { get; set; }        

Prevents the ContentArea container from saving until only the correct types are included.

 

regards,

Danny

#79808
Edited, Jan 08, 2014 9:19
Vote:
 

Thanks @Alabin

The solution was to add a "using EpiServer;"

It helped me too.

#155497
Sep 19, 2016 14:24
This thread is locked and should be used for reference only. Please use the Episerver CMS 7 and earlier versions forum to open new discussions.