2017-06-16 3 views
1

Ich habe einen Blocktyp, den ich in einem bestimmten Inhaltsbereich auf einer bestimmten Seite verwende. Gibt es einen Weg, den ich validieren kann (auf Seitenebene oder Inhaltsebene), dass Block nicht mehr als einmal verwendet wird?Wie schränkt man die Anzahl eines im Contentbereich verwendeten Blocktyps ein?

+0

Möchten Sie Stellen Sie sicher, dass es nur einen Block im Inhaltsbereich gibt, einen Block dieses Typs (aber möglicherweise mit m verschiedene andere Arten) oder beides? Ich denke, dass dies mit einem Validierungsdekorator ziemlich ohne die Ereignishaken unten getan werden kann. – egandalf

Antwort

2

Hier ist eine Beispielvalidierungsattributklasse, die helfen sollte. Ich arbeite an einem "Validierungsregeln" nugget-Paket, von dem ich dachte, dass es das einschließen könnte. Ich habe nur die Regel "Min nach Objekttyp" hinzugefügt, aber vor der Veröffentlichung weitere hinzugefügt.

Klasse:

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}"; 
     } 
    } 
} 

Beispielanwendung auf einem Inhaltsbereich:

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

Ergebnis in Editor-Ansicht, wenn ungültig (verhindert veröffentlichen):

enter image description here

1

Nichts eingebaut, aber Sie können einfach an die Ereignisse SavingContent oder PublishingContent anschließen und den Inhalt validieren, bevor er gespeichert/veröffentlicht wird.

Beispiele here und there.

Verwandte Themen