Five New Optimizely Certifications are Here! Validate your expertise and advance your career with our latest certification exams. Click here to find out more
Five New Optimizely Certifications are Here! Validate your expertise and advance your career with our latest certification exams. Click here to find out more
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>();
}
}
I get an error for GetOriginalType(). It says EPiServer.Core.IContent does not contain a definition for this. How can I fix this?
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.
I found this on nuget and it solves all of my problem with ContentAreas restrictions.
http://www.nuget.org/packages/OpenWaves.EPiServer.ExtendedContentAreaEditor/
"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.
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
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.