Five New Optimizely Certifications are Here! Validate your expertise and advance your career with our latest certification exams. Click here to find out more

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.