Hi Benjamin,
You can decorate content areas with the AllowedTypes attribute.
So if I want to say that a content areas can contain all but that one block, how would I do that?
Create a base class/interface which all block types should implement? It's also possible to create a page validator, but it doesn't provide nice editing experience.
The AllowedTypes attribute has RestrictedTypes property: http://world.episerver.com/documentation/Items/Developers-Guide/Episerver-CMS/9/Content/Properties/Property-types/Restricting-content-types-in-properties/
There isn't a way I can declare on my block that it is only allowed in tagged content areas? Would be easier specifying this logic on the block rather than all the content areas.
How about creating a specific interface that you add to your Block?
For example:
public interface ITaggedContent : IContentData { } [UIDescriptorRegistration] public class TaggedContentUiDescriptor : UIDescriptor<ITaggedContent> { }
Implement this interface on your Content
public class MyBlock : BlockData, ITaggedContent { } public class MyPage : PageData, ITaggedContent { }
And on your ContentArea add the AllowedTypes as Dejan mentions
[AllowedTypes(AllowedTypes = new[] { typeof(ITaggedContent) })] public virtual ContentArea MyContentArea { get; set; }
You will need to have the UiDescriptor, otherwise AllowedTypes will not be able to understand that your pages and blocks implement this interface.
I don't think that is what I need. I have a block SpecificBlock that I want to make sure is only placed on pages with page type SpecificPage. How do I go about this?
Since there are no "exclude" for this in Episerver but only "include" there are no easy way to do this.
One way could maybe be to use the IValidate interface for all content types that would go through all ContentAreas on the content and make sure that the block is not added.
http://world.episerver.com/documentation/Class-library/?documentId=cms/10/2D086E18
So roughly the code should do
if(instance is SpecificPage) { return Enumerable.Empty<ValidationError>(); }
and then loop all properties and validate each property value that is a ContentArea and send an error if something is wrong
var contentLoader = ServiceLocator.Current.GetInstance<IContentLoader>(); var errors = new List<ValidationError>(); foreach (PropertyData property in CurrentPage.Property) { var contentArea = property.Value as ContentArea; if (contentArea == null) { continue; } var contentLinks = contentArea.Items.Select(i => i.ContentLink); var contentAreaContainsSpecificBlock = contentLoader.GetItems(contentLinks, LanguageSelector.AutoDetect(true)).Any(content => content is SpecificBlock); if (contentAreaContainsSpecificBlock) { errors.Add(new ValidationError { ErrorMessage = $"{property.TranslateDisplayName()} contains SpecificBlock", Severity = ValidationErrorSeverity.Error }); } } return errors;
It's just an idea but maybe something you can build on
I am making a block that must only be put in few selected content areas. How do I go about this?