Shared Field Mapping mit GlassMapper V5

Geschrieben von Anna Bründel veröffentlich am in der Kategorie Sitecore
Als wir die Basiskomponenten für ein neues Projekt mit Sitecore 9 und GlassMapper V5 aufbauten und die Templates anlegten, fiel uns ein Problem mit den Shared Fields auf: Wenn man ein Item über ein Shared Field mappt, wird null zurückgegeben.

SC Standard vs. GlassMapper

Sitecore selbst liefert über die Funktion Context.Database.GetItem(ID_des_Items) immer ein Item zurück, sofern es in irgendeiner Sprache existiert und nicht nur in der Kontextsprache.

GlassMapper macht Folgendes: Hat das angefragte Item keine Version in der Kontextsprache, bekommt man null zurück. Das Tolle daran ist, dass wir uns nun den Mehrfach-Check sparen können, ob das Item tatsächliche eine Sprachversion hat.

 

Das Problem mit den Shared Fields

Nun haben wir aber folgendes Problem: Wenn das Feld Shared ist, über das wir ein Item mappen wollen, bekommen wir immer null zurück, außer wir fügen eine Version des referenzierten Items in der entsprechenden Sprache hinzu.

Beispielsweise haben wir in unserem Sitecore Web globale Ressourcen als Items abgelegt, die wir ausschließlich immer in der Systemsprache Englisch anlegen und deren Felder alle Shared sind.

 

GlassMapper V4

Für Version 4 des GlassMappers haben wir bei unseren Recherchen eine sehr gute Lösung für dieses Problem gefunden:

https://ctor.io/shared-field-references-in-glass-mapper/ .

Man implementiert ein Custom Attribut und dessen Configuration und TypeMapper, konfiguriert das Ganze in der CastleConfig (Konfiguration für das Dependency Management) und das war's.

Leider funktioniert dies in der Version 5 so nicht.

 

Die Lösung für GlassMapper V5

Nach langem Suchen und selbst in den Code von GlassMapper auf github ( https://github.com/mikeedwards83/Glass.Mapper ) schauen fanden wir heraus: Der VersionCountDisabler wurde entfernt.

Also implementierten wir eine andere Lösung, die der aus dem Blogbeitrag zu GlassMapper V4 sehr ähnlich ist.

 

Custom Configuration

Wir haben eine eigene Konfiguration hinzugefügt und dort die Copy()_Methode überschrieben, damit unsere Konfiguration auch kopiert wird.

 public class SitecoreSharedFieldConfiguration : SitecoreFieldConfiguration {
protected override AbstractPropertyConfiguration CreateCopy() {
return new SitecoreSharedFieldConfiguration();
}
   protected override void Copy(AbstractPropertyConfiguration copy) {
SitecoreSharedFieldConfiguration config = copy as SitecoreSharedFieldConfiguration;
base.Copy(copy);
}

Custom Attribut

Implementiert haben wir dann das SitecoreSharedFieldAttribute, das vom SitecoreFieldAttribute von GlassMapper erbt. Dort mussten wir die Methode AbstractPropertyConfiguration() überschrieben, um unsere Konfiguration zu ziehen.

 

public class SitecoreSharedFieldAttribute : SitecoreFieldAttribute {
 public SitecoreSharedFieldAttribute() {}
 public SitecoreSharedFieldAttribute(string fieldName): base(fieldName) {}
 public override AbstractPropertyConfiguration Configure(PropertyInfo propertyInfo) { 
SitecoreSharedFieldConfiguration config = new SitecoreSharedFieldConfiguration();
this.Configure(propertyInfo, config);
return config;
}
 public void Configure(PropertyInfo propertyInfo, SitecoreSharedFieldConfiguration config) {
/* Your custom config here...
* Create a property ex. "Type" and define it to your config.
Ex. config.Type = this.Type; */
base.Configure(propertyInfo, config);
}


Custom FieldTypeMapper

Damit unser Attribut verwendet werden kann, haben wir einen neuen FieldTypeMapper hinzugefügt, in dem wir die GetFieldValue()-Methode überschrieben, um die Property VersionCount auf false zu setzen, damit wir ein Item mappen können, auch wenn es keine Version in der Kontextsprache gibt.

 public class SitecoreSharedFieldTypeMapper : SitecoreFieldTypeMapper {
  public override object GetFieldValue(
string fieldValue, SitecoreFieldConfiguration config, SitecoreDataMappingContext context) {
GetOptionsSc scOptions = context.Options as GetOptionsSc;
if (scOptions != null) {
scOptions.VersionCount = false;
}
return base.GetFieldValue(fieldValue, config, context);
}
}

TypeMapper registrieren

Zum Abschluss musste der neue FieldTypeMapper nur noch in der GlassMapperScCustom.cs Datei in App_Start registriert werden.

 public static class GlassMapperScCustom  {
public static IDependencyResolver CreateResolver()
{
Config config = new Config();
DependencyResolver dependencyResolver = new DependencyResolver(config);
// Adding sitecore shared field type mapper.
dependencyResolver.DataMapperFactory.First(() => new SitecoreSharedFieldTypeMapper());
// add any changes to the standard resolver here
return dependencyResolver;
}
}

Nutzung des Attributs

Nachdem wir nun alles Nötige eingerichtet haben, kann das Attribut in den Models verwendet werden, wie z.B.:

 [SitecoreSharedField]
public virtual Icon Icon { get; set; }
Und das war auch schon alles! Wie man sehen kann ist der Weg dem mit GlassMapper V4 sehr ähnlich.