EPiserver 7 обязательное свойство в дополнительном блоке

Я сделал ImageBlock со свойством ImageUrl и свойством Description. ImageUrl требуется.

[ContentType(
    DisplayName = "Image",
    Description = "Image with description and caption",
    GUID = "387A029C-F193-403C-89C9-375A2A6BF028",
    AvailableInEditMode = false)]
public class ImageBlock : BaseBlock
{
    [Required]
    [UIHint(UIHint.Image)]      
    [Display(
        Name = "Image Url",
        Description = "",
        GroupName = SystemTabNames.Content,
        Order = 10)]      
    public virtual Url ImageUrl { get; set; }

    [Display(
        Name = "Image Description",
        Description = "A description of the image",
        GroupName = SystemTabNames.Content,
        Order = 20)]      
    public virtual string Description { get; set; }

}

Моя ArticlePage использует этот ImageBlock для своего свойства Image, но не обязательно иметь изображение в статье. Однако, если редактор выбирает изображение, URL-адрес должен быть обязательным.

[Display(
    Name = "Image",
    Description = "",
    GroupName = SystemTabNames.Content,
    Order = 20)]
public virtual ImageBlock Image { get; set; }

Но когда я создаю новый экземпляр ArticlePage, у меня запрашивают ImageUrl, который, как утверждает EPiServer, требуется. Я что-то пропустил?

1 ответ

Решение

Я нашел способ создать пользовательский атрибут, который проверяет, дает ли ошибка, если установлены какие-либо другие значения, кроме требуемого свойства блока. Так что в моем случае, если, например, редактор вводит значение для Image Description и пытается опубликовать без указания ImageUrl, появится сообщение об ошибке.

Код выглядит так:

public class RequiredBlockPropertyAttribute : ValidationAttribute
{
    private string _failedOnProperty = string.Empty;

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        return ValidateBlock(value, validationContext) 
            ? ValidationResult.Success 
            : new ValidationResult(FormatErrorMessage(validationContext.DisplayName));
    }

    private bool ValidateBlock(object value, ValidationContext validationContext)
    {
        var type = validationContext.ObjectType.BaseType;
        if (type == null)
            return true;

        var properties = type.GetProperties().Where(prop => 
            prop.DeclaringType != null 
            && prop.DeclaringType.IsSubclassOf(typeof(BlockData)));

        foreach (var property in properties)
        {
            if (!property.Name.Equals(validationContext.DisplayName))
            {
                var val = property.GetValue(validationContext.ObjectInstance, null);
                if (val != null && (value == null || IsDateTimeMinValue(value)))
                {
                    _failedOnProperty = property.Name;
                    return false;
                }
            }
        }

        return true;
    }

    private static bool IsDateTimeMinValue(object value)
    {
        DateTime t;
        DateTime.TryParse(value.ToString(), out t);

        return t == DateTime.MinValue;

    }

    public override string FormatErrorMessage(string name)
    {
        return string.Format(ErrorMessageString, name, _failedOnProperty);
    }

И использование в блоке:

    [RequiredBlockProperty(
        ErrorMessage = "{1} cannot be set without {0} defined")]
    [UIHint(UIHint.Image)]       
    [Display(
        Name = "Image Url", 
        Description = "", 
        GroupName = SystemTabNames.Content, 
        Order = 10)]       
    public virtual Url ImageUrl { get; set; } 
Другие вопросы по тегам