Ограничить блоки в 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; }
Другие вопросы по тегам