November Happy Hour will be moved to Thursday December 5th.

How to achieve CMS validation in container block level

Vote:
 

Hi Team,

I need your suggestion on how we can achieve CMS validation in block level.

Scenario:

  • As per the requirement, I must create a container block which contains minimum one card and maximum ‘n’ number of cards. The container won’t be displayed if it has less than one card.
  • As per the actual functionality in CMS, when we create container and cards in separate folder and then map cards to the container it works as expected.
  • But when the container is directly created from the page level, I see the below error.
  • Error:  "Unable to load /episerver/cms/Stores/contentdata/ Status : 404"

 

Question: When the container is directly created from the page level, how can we put a CMS validation message to have at least one card in that container block?

For example, instead of the above error, I must be able to see the validation message saying, “Minimum one card is required to create a container.”

Please help.

Thanks!

#298700
Mar 21, 2023 11:39
Vote:
 

I'm assuming you have a content area in your Container Block where you can add additional card blocks ? 

If this is the case can you implement IValidate e.g. 

    /// <summary>
    /// Validates a <see cref="T:Netcel.Models.Blocks.VideoSlideBlock"/> instance
    /// </summary>
    public class VideoSlideBlockValidator : IValidate<VideoSlideBlock>
    {
        private List<ValidationError> _errors;
        private VideoSlideBlock _instance;

        /// <summary>
        /// Validates the <see cref="T:Netcel.Models.Blocks.VideoSlideBlock"/> instance
        /// </summary>
        IEnumerable<ValidationError> IValidate<VideoSlideBlock>.Validate(VideoSlideBlock instance)
        {
            _instance = instance;
            _errors = new List<ValidationError>();

            ValidateVideoSourcesContentArea();

            return _errors;
        }

        /// <summary>
        /// Checks that the VideoSourcesContentArea contains at least one VideoFile
        /// </summary>
        private void ValidateVideoSourcesContentArea()
        {
            if (_instance.VideoSourcesContentArea != null && _instance.VideoSourcesContentArea.Items != null)
            {
                var videoFound = false;
                foreach (var item in _instance.VideoSourcesContentArea.Items)
                {
                    var contentLoader = ServiceLocator.Current.GetInstance<IContentLoader>();

                    VideoFile file;
                    if (contentLoader.TryGet(item.ContentLink, out file))
                    {
                        videoFound = true;
                        break;
                    }
                }
                if (!videoFound)
                {
                    _errors.Add(GetMissingVideoError("VideoSourcesContentArea"));
                }
            }
            else
            {
                _errors.Add(GetMissingVideoError("VideoSourcesContentArea"));
            }
        }

        /// <summary>
        /// Returns a missing video error
        /// </summary>
        private ValidationError GetMissingVideoError(string propertyName)
        {
            return new ValidationError
            {
                ErrorMessage = propertyName + " must contain at least 1 video item",
                PropertyName = propertyName,
                Severity = ValidationErrorSeverity.Error,
                ValidationType = ValidationErrorType.AttributeMatched
            };
        }
    }
#298704
Mar 21, 2023 13:41
Vote:
 

Assuming you are talking about the content area, in addition to what Minesh suggested, you can also create a custom validation attribute that can allow you to set the range.

Something like below (untested):

   // Custom attribute validator
    [AttributeUsage(AttributeTargets.Property)]
    public class ContentAreaItemsAllowedAttribute : ValidationAttribute
    {
        private int _max;
        private int _min;

        /// Constructor with given max
        public MaxItemsAttribute(int min, int max)
        {
            _min = min;
            _max = max;
        }

        // Check if it is valid
        public override bool IsValid(object value)
        {
            string error = $"The number of items in the Content area should be between {_min} and {_max} items!";

            var contentArea = value as ContentArea;
            var count = contentArea?.FilteredItems?.Count()
            if (count > _max || count < _min)
            {
                ErrorMessage = error;
                return false;
            }
            return true;
        }

        /// Return Result
        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            var result = base.IsValid(value, validationContext);
            if (!string.IsNullOrWhiteSpace(result?.ErrorMessage))
            {
                result.ErrorMessage = $"{validationContext.DisplayName} {ErrorMessage}";
            }
            return result;
        }
    }
}

And then in your Block/Page:

[Display(
    Name = "Video Items",
    Description = "Video Items.",
    GroupName = "Content",
    Order = 10)]
 [ContentAreaItemsAllowed(1,5)]
 public virtual ContentArea VideoItems { get; set; }
#298712
Edited, Mar 21, 2023 16:33
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.