Как ограничить количество типов блоков, используемых в области содержимого?

У меня есть тип блока, который я использую в определенной области контента на определенной странице. есть ли способ проверить (на уровне страницы или области содержимого), что блок не используется более одного раза?


person SWAZ    schedule 16.06.2017    source источник
comment
Вы хотите убедиться, что в области контента есть только один блок, один блок этого типа (но, возможно, с несколькими другими типами) или оба? Я думаю, что это можно легко сделать с помощью декоратора проверки без хуков событий ниже.   -  person egandalf    schedule 25.07.2017


Ответы (2)


Вот пример класса атрибута проверки, который должен помочь. Я работаю над пакетом nuget «Правила проверки», который, как я думал, может включать это. Я включил только правило «Минимум по типу объекта», но добавлю еще, прежде чем оно будет выпущено.

Учебный класс:

using EPiServer;
using EPiServer.Core;
using EPiServer.ServiceLocation;
using System;
using System.ComponentModel.DataAnnotations;
using System.Reflection;

namespace eGandalf.Epi.Validation.Lists
{
    /// <summary>
    /// Detects whether the minimum required items of a specific type within a ContentArea condition has been met. Only supports items that can be loaded by IContentLoader. Supports type inheritance.
    /// </summary>
    [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = true, Inherited = true)]
    public class MinimumOfTypeAttribute : ValidationAttribute
    {
        public int Limit { get; }
        public Type ObjectType { get; }

        public MinimumOfTypeAttribute(int limit, Type t)
        {
            Limit = limit;
            ObjectType = t;
        }

        public override bool IsValid(object value)
        {
            if (value == null && Limit > 0) return false;

            var area = value as ContentArea;
            if (area != null) return ValidateContentArea(area);

            throw new TypeMismatchException("Minimum of type only works with ContentArea properties.");
        }

        private bool ValidateContentArea(ContentArea area)
        {
            if (area?.Items?.Count < Limit) return false;

            var typeCount = 0;
            foreach (var item in area.Items)
            {
                if (CanLoadContentByType(item.ContentLink))
                {
                    typeCount++;
                    // Return as soon as the validation is true.
                    if (typeCount >= Limit) return true;
                }
            }
            return false;
        }

        private bool CanLoadContentByType(ContentReference reference)
        {
            var loader = ServiceLocator.Current.GetInstance<IContentLoader>();
            var loaderType = loader.GetType();
            MethodInfo getMethod = loaderType.GetMethod("Get", new Type[] { typeof(ContentReference) });
            MethodInfo genericGet = getMethod.MakeGenericMethod(new[] { ObjectType });

            try
            {
                var content = genericGet.Invoke(loader, new object[] { reference });
                return content != null;
            }
            catch (Exception ex)
            {
                return false;
            }
        }

        public override string FormatErrorMessage(string name)
        {
            return $"ContentArea {name} must include at least {Limit} items of type {ObjectType.Name}";
        }
    }
}

Пример приложения в области содержимого:

[MinimumOfType(1, typeof(RssReaderBlock))]
public virtual ContentArea RelatedContentArea { get; set; }

Результат в представлении редактора, когда он недействителен (предотвращает публикацию):

введите здесь описание изображения

person egandalf    schedule 25.07.2017

Ничего встроенного, но вы можете легко подключиться к событиям SavingContent или PublishingContent и проверить контент перед его сохранением/публикацией.

Примеры rel="nofollow noreferrer">здесь и здесь.

person Ted Nyberg    schedule 16.06.2017