Ограничить блоки в ContentArea
У меня возникла проблема, ограничивающая тип блока, который нужно вставить в ContentArea. Я хочу, чтобы свойство ContentArea объекта SliderBlock могло содержать только вставку объекта 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, я получу бесконечный цикл, и он разрушит сайт. Это то, что я пытаюсь контролировать.
5 ответов
Если вы используете EPiServer 7.5, встроено ограничение, какие блоки вы можете использовать в области содержимого. Подробнее см. В этом сообщении в блоге: Ограничение разрешенных типов в области содержимого.
Пример кода из поста блога:
[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");
}
}
Начиная с EpiServer 8, появился новый атрибут [AllowedTypes]. Теперь это лучший способ ограничения блоков. Это преодолевает множество ограничений [AvailableContentTypes]. Когда вы перетаскиваете блоки в область содержимого, проверка фактически работает.
Пример кода может быть
[AllowedTypes(new []{ typeof(SlideBlock) })]
public virtual ContentArea Slides { get; set; }
Вот хороший пример кода здесь Как ограничить блоки, разрешенные в области содержимого Episerver
Также этот на EpiWorld http://world.episerver.com/blogs/Ben-McKernan/Dates/2015/2/the-new-and-improved-allowed-types/
Из вас еще не было обновлено до 7.5, как Фредерик предполагает, что у нас есть следующий атрибут, который мы создали для этого.
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; }
НТН
Адам
Создайте класс проверки и реализуйте интерфейс IValidate из EPiServer.validation. Проверка этого хранится вне классов 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;
}
}
Подробнее читайте по адресу http://sdkbeta.episerver.com/SDK-html-Container/?path=/SdkDocuments/CMS/7/Knowledge%20Base/Developer%20Guide/Validation/Validation.htm&vppRoot=/SdkDocuments//CMS/7/Knowledge%20Base/Developer%20Guide/
Если вы обновились до EPi 7.5, вы можете использовать аннотацию AllowedTypes
[AllowedTypes(new [] {typeof(SlideItemBlock)})]
public virtual ContentArea Slides { get; set; }
Я не знаю, можете ли вы настроить какие-либо сообщения с помощью более позднего решения. Есть несколько известных ограничений
- Ограничение не работает для оверлеев при редактировании на странице. Это ошибка, которая была исправлена и будет выпущена в патче через несколько недель.
- Нет проверки сервера. В настоящее время атрибут только добавляет ограничение в пользовательском интерфейсе. Мы надеемся, что скоро сможем добавить поддержку проверки сервера, что также даст возможность проверить ваши пользовательские свойства.
- Нет проверки при создании локальных блоков в областях содержимого. Если вы используете новую функцию для добавления локальных блоков в область содержимого, в настоящее время фильтрация типов содержимого при создании нового блока отсутствует.
Узнайте больше на http://world.episerver.com/Blogs/Linus-Ekstrom/Dates/2013/12/Restriction-of-content-types-in-properties/
В общем, первое решение в настоящее время лучшее.
Вы можете добавить атрибут проверки в свойство области содержимого, чтобы ограничить допустимые типы блоков. Смотрите эту ссылку для подробного примера.
Затем, используя атрибут AvailableContentTypes, вы можете ограничить доступ только к типам SlideItemBlock.
[Required]
[Display(Name = "Slides")]
[AvailableContentTypes(Include = new []{typeof(SlideItemBlock)})]
public virtual ContentArea Slides { get; set; }