How to avoid duplicates of contents in a ContentArea

Vote:
 

Is there an easy way to avoid duplicates in the ContentArea?

Have searched but not found much.... I prefer not to hook up in publish event att do the check myself..

Attribute like [DisableDuplicates] would have been perfect here

#147526
Apr 18, 2016 10:49
Vote:
 

How about creating a custom validator for this? You could either give a warning or an error message to the editors.

http://henrikm.com/custom-episerver-property-validation/

#147528
Apr 18, 2016 11:01
Vote:
 

Yes, I tried it and it works perfectly!!

Thanks a lot, this made my day :)

A minor thing... would be great to be able to present the actual proprerty display name to the editor (and not the actual property name)...

#147529
Apr 18, 2016 11:27
Vote:
 

Great! 
Regarding the display name, you could check out Grzegorz answer in this forum thread: http://world.episerver.com/forum/developer-forum/Developer-to-developer/Thread-Container/2015/8/localized-property-name-in-validation/

#147530
Apr 18, 2016 11:48
Vote:
 

Yes I found his answer and borrowed it :-)

Here is the code if anyone is interested, not many rows

[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)]
	public sealed class DisableDuplicates : ValidationAttribute
	{
		protected override ValidationResult IsValid(object value, ValidationContext validationContext)
		{
			var propertyDefinitionRepository = EPiServer.ServiceLocation.ServiceLocator.Current.GetInstance<IPropertyDefinitionRepository>();
			var propertyDefinitionId = ((PageData)validationContext.ObjectInstance).Property[validationContext.MemberName].PropertyDefinitionID;
			var propertyDefinition = propertyDefinitionRepository.Load(propertyDefinitionId);
			propertyDefinition.LocalizationService = LocalizationService.Current;

			if (IsDuplicate(value as ContentArea))
			{
				return new ValidationResult(
					$"You can not have duplicate content in: '{propertyDefinition.TranslateDisplayName()}'",
					new[] { validationContext.MemberName });
			}

			return ValidationResult.Success;
		}

		bool IsDuplicate(ContentArea area)
		{
			if (area == null || area.IsEmpty)
				return false;

			if (area.Items == null || area.Items.Any() == false)
				return false;

			List<int> items = new List<int>();

			foreach (var cai in area.Items)
			{
				if (items.Contains(cai.ContentLink.ID))
					return true;

				items.Add(cai.ContentLink.ID);
			}

			return false;
		}
	}
#147531
Apr 18, 2016 11:49
Vote:
 

Thanks for sharing! :-)

#147534
Apr 18, 2016 11:53
Vote:
 

Sounds like a good solution. I might steal it :)

#147537
Apr 18, 2016 12:10
Vote:
 

You could also simplify IsDuplicate method to single line expression :)

private bool IsDuplicate(ContentArea area)
{
    return area?.Items.DistinctBy(c => c.ContentLink.ToReferenceWithoutVersion()).Count() != area?.Items.Count;
}
#147545
Apr 18, 2016 13:24
Vote:
 

Excellent!

#147548
Apr 18, 2016 13:44
This topic was created over six months ago and has been resolved. If you have a similar question, please create a new topic and refer to this one.
* 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.