我遇到了限制在ContentArea中插入哪种Block的问题。我想要的是SliderBlock的ContentArea属性只能插入一个SlideItemBlock。
[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
}
或者这是否是错误的方法来实现我试图限制编辑器不拖放错误的块类型?
截至目前,我可以创建一个SliderBlock并在其中插入一个SlideItemBlocks。如果我然后在新的SliderBlock中插入创建的SliderBlock,我会得到一个永远的循环,它会打破网站。这就是我想控制的。
答案 0 :(得分:5)
如果您使用的是EPiServer 7.5,则可以限制内容区域中可以使用的块。有关详细信息,请查看此博客文章:Restricting the allowed types in a content area。
博客文章中的代码示例:
[EditorDescriptorRegistration(TargetType = typeof(ContentArea), UIHint = "Gallery")]
public class ImageGalleryEditorDescriptor : EditorDescriptor
{
public ImageGalleryEditorDescriptor()
{
// Setup the types that are allowed to be dragged and dropped into the content
// area; in this case only images are allowed to be added.
AllowedTypes = new Type[] { typeof(IContentImage) };
// Unfortunetly the ContentAreaEditorDescriptor is located in the CMS module
// and thus can not be inherited from; these settings are copied from that
// descriptor. These settings determine which editor and overlay should be
// used by this property in edit mode.
ClientEditingClass = "epi-cms.contentediting.editors.ContentAreaEditor";
OverlayConfiguration.Add("customType", "epi-cms.widget.overlay.ContentArea");
}
}
答案 1 :(得分:2)
从EpiServer 8开始,有一个名为[AllowedTypes]的新属性。这是限制块的最佳方法。它克服了[AvailableContentTypes]的许多限制。将块拖动到内容区域时,验证确实有效。
示例代码段是
[AllowedTypes(new []{ typeof(SlideBlock) })]
public virtual ContentArea Slides { get; set; }
这里有一个很好的代码示例How To Restrict The Blocks Allowed Within A Content Area Episerver
这也是关于EpiWorld的http://world.episerver.com/blogs/Ben-McKernan/Dates/2015/2/the-new-and-improved-allowed-types/
答案 2 :(得分:1)
你还没有升级到7.5,因为Frederik建议我们创建以下属性来做这件事。
using EPiServer.Core;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
namespace xxx.Com.Core.Attributes
{
[AttributeUsage(AttributeTargets.Property)]
public class OurAvailableContentTypesAttribute : ValidationAttribute
{
public Type[] Include { get; set; }
public Type[] Exclude { get; set; }
public override bool IsValid(object value)
{
if (value == null)
{
return true;
}
if (!(value is ContentArea))
{
throw new ValidationException("OurAvailableContentTypesAttribute 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 ValidationResult IsValid(object value, 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;
}
}
}
然后使用
public class OurBlock : BlockData
{
[CultureSpecific]
[Editable(true)]
[Display(Name = "",
Description = "",
GroupName = SiteConstants.GroupNames.ContentArea,
Order = 1)]
[OurAvailableContentTypes(Include = new[] { typeof(OurImageBlock) })]
public virtual ContentArea ImageContentArea { get; set; }
HTH
亚当
答案 3 :(得分:0)
创建验证类并从EPiServer.validation实现IValidate接口。对此的验证保留在PageData和BlockData类之外。
这应该是你要找的东西
using System.Collections.Generic;
using System.Linq;
using EPiServer.Validation;
public class SliderBlockValidator : IValidate<SliderBlock>
{
public IEnumerable<ValidationError> Validate(SliderBlock instance)
{
var errors = new List<ValidationError>();
if (instance.Slides != null &&
instance.Slides.Contents.Any(x => x.GetType().BaseType != typeof (SlideItemBlock)))
{
errors.Add(new ValidationError()
{
ErrorMessage = "Only SlideItemBlocks are allowed in this area",
PropertyName = "Slides",
Severity = ValidationErrorSeverity.Error,
ValidationType = ValidationErrorType.StorageValidation
});
}
return errors;
}
}
如果已升级到EPi 7.5,则可以使用AllowedTypes注释
[AllowedTypes(new [] {typeof(SlideItemBlock)})]
public virtual ContentArea Slides { get; set; }
我不知道您是否能够使用更高版本的解决方案自定义任何消息。有一些已知的限制
总而言之,第一个解决方案目前是更好的解决方案。
答案 4 :(得分:-1)
您可以向内容区域属性添加验证属性,以限制允许的块类型。 有关详细示例,请参阅this link。
然后使用AvailableContentTypes属性,您可以限制为仅允许SlideItemBlock类型。
[Required]
[Display(Name = "Slides")]
[AvailableContentTypes(Include = new []{typeof(SlideItemBlock)})]
public virtual ContentArea Slides { get; set; }