Mit dem Oktober Refresh 27.0.0 wurde in Xperience by Kentico die grundlegende Architektur umgebaut.
Statt mit TreeNodes und DocumentTypes haben wir es hier ab sofort mit Content Items und deren Sonderform Pages zu tun.
Die DocumentQuery und die MultiDocumentQuery sind entsprechend entfernt worden.
Wie fragen wir also ab jetzt unsere Page Daten aus der Datenbank ab?
Was war – Was ist
Wenn wir uns auf die Pages und die Baumstruktur in der Pages App konzentrieren, dann kann man die entsprechende neue Struktur ungefähr so interpretieren:
Vor XbyK 27.0.0 | Ab XbyK 27.0.0 |
---|---|
TreeNode (Page Content Items) | IWebPageFieldsSource |
TreeNode Eigenschaften | [MyContentTypeClass].SystemFields |
DocumentQuery | ContentTypeQueryParameters |
MultiDocumentQuery | ContentItemQueryBuilder |
Content Items
Content Items können jetzt auch im Content Hub angelegt werden. Hier legen wir alles an, was nicht in direktem Zusammenhang mit einem konkreten Webseiten Kanal steht und in verschiedenen Kanälen genutzt werden kann (muss nicht zwingend eine Webseite sein).
Die Content Items haben daher sinnigerweise keinen Bezug zu einer Webseitenstruktur mehr.
Sie nutzen statt dessen definierbare Beziehungen zueinander.
Daher entfallen diese Page Eigenschaften und wir brauchen nur die grundlegenden Content Item Eigenschaften:
Diese Aufspaltung des TreeNodes in diese zwei Teilbereiche macht vor dem neuen Hintergrund durchaus Sinn.
Pages
Eine Page ist ein Content Item welches in der Pages App angelegt wird und von einem User besucht werden kann (Eine URL hat).
Eine Page liegt in einer Baumstruktur in Parent-Child Beziehung zu anderen Pages im Content Tree vor.
Schauen wir uns den automatisch generierten Code eines Content Types vom Typ „Page“ einmal an, dann fällt folgendes auf:
/// <summary> /// Represents a page of type <see cref="Homepage"/>. /// </summary> public partial class Homepage : IWebPageFieldsSource { /// <summary> /// Code name of the content type. /// </summary> public const string CONTENT_TYPE_NAME = "Xel.Homepage"; /// <summary> /// Represents system properties for a web page item. /// </summary> public WebPageFields SystemFields { get; set; }
Vorher war dies:
/// <summary> /// Represents a content item of type Homepage. /// </summary> public partial class Homepage : TreeNode { #region "Constants and variables" /// <summary> /// The name of the data class. /// </summary> public const string CLASS_NAME = "Xel.Homepage";
Da jetzt alles ein Content Item ist und nicht mehr ausschließlich in einer Baumstruktur angelegt wird macht die Änderung hier Sinn.
Statt einem TreeNode haben wir also ein Content Item, welches zusätzlich das Interface IWebPageFieldsSource implementiert.
Dadurch wird das Content Item mit allen Feldern erweitert, die im Zusammenhang mit der Baumstruktur aus der Pages App stehen.
Das Interface stellt das WebPageFields Objekt „SystemFields“ sicher.
Konkrete Pages abfragen
Wir fangen erstmal mit einem QueryBuilder an.
Als Teil der Abrage (Hauptabfrage) filtern wir dann zuerst erstmal nach dem Typ den wir abfragen wollen. Das können auch mehrere sein.
Danach können wir für diese Typen noch weitere Details in einer untergeordneten Abfrage ergänzen (Unterabfrage).
Globale Parameter werden zuletzt zu dem ganzen Paket aus abgefragten Typen und deren Details hinzugefügt.
Um die Abfrage am Ende auszuführen nutzen wir einen QueryExecutor und mappen das Ergebnis dann direkt auf ein passendes Objekt.
Dafür gibt es zwei Hauptmethoden am Executor. Einmal GetResult() und einmal GetWebPageResult() für die Sondervariante „Page“ Content Item.
Das ist erstmal eine Umgewöhnung, aber je mehr man sich damit befasst umso mehr Vorteile werden durch diesen neuen Ansatz klar.
string pagePath = "[PATH TO YOUR PAGE IN THE PAGE TREE]"; IWebsiteChannelContext siteContext = Service.Resolve<IWebsiteChannelContext>(); IContentQueryExecutor queryExecutor = Service.Resolve<IContentQueryExecutor>(); // get current page context WebPageDataContext pageContext = pageContextRetriever.Retrieve(); // query builder to retrieve pageFilter in path ContentItemQueryBuilder pageFilterBuilder = new ContentItemQueryBuilder() .ForContentType( nameof(DocumentFilter.CONTENT_TYPE_NAME), query => query .ForWebsite( siteContext.WebsiteChannelName, PathMatch.Single(pagePath))) .InLanguage(pageContext.WebPage.LanguageName); // get the DocumentFilter page DocumentFilter documentFilter = (await queryExecutor .GetWebPageResult( builder: pageFilterBuilder, resultSelector: result => resultMapper.Map<DocumentFilter>(result)) ) .FirstOrDefault();
Verschiedene Pages abfragen
Etwas komplexer ist die Abfrage wenn man mehrere Typen zusammen abfragen möchte.
Zu diesem Zweck können wir mehrere .ForWebsite subqueries an einen Builder anhängen.
Auf diese Weise gibt uns der Executor dann verschiedene Typen zurück.
Das Mapping des Results auf einen Datentyp muss dann entsprechend berücksichtigt werden.
In diesem Beispiel möchte ich gerne alle Pages abfragen, in denen einige Properties gleich sind (Vererbung kommt im Frühjahr 2024).
Aus dem Ergebnis der Abfrage möchte ich dann auf die Werte in diesen gemeinsamen Eigenschaften zugreifen.
foreach(string contentTypeName in BasePageInheritorClassnames) { builder = builder .ForContentType(contentTypeName, query => query .ForWebsite( siteContext.WebsiteChannelName, PathMatch.Children(pagePath, nestingLevel))); } IEnumerable<BasePage> pages = await queryExecutor.GetWebPageResult( builder: builder, resultSelector: result => resultMapper.Map<BasePage>(result));
Fazit
Die neue Architektur und das Umdenken von reinen Webseiten hin zu modernen Content Beziehungen und Ausgaben auf mehreren Kanälen ist eine gewaltige Umgewöhnung insbesondere für die Entwickler (zu denen ich mich auch zähle), die seit Dekaden mit den DocumentQueries und den TreeNodes arbeiten.
Der Schritt war jedoch notwendig und bietet viel mehr Möglichkeiten um den Content aus der Xperience by Kentico ↗ DXP abzufragen.
Ich würde raten ein Repository Layer einzurichten um die Abfragen zentral zu verwalten und in Zukunft an einer Stelle anpassen zu können sobald mehr Features in XbyK implementiert werden die dies erlauben.
Schreibe einen Kommentar
Du musst angemeldet sein, um einen Kommentar abzugeben.