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!

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.
* 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.