Creating a custom searchable index for an external data source in Sitecore

Creating custom Search index for external source in Sitecore - Teaser

I am sure that all of you have created a regular item index for Sitecore with Solr or Lucene in the past already. I got to the challenge that I needed to call an external service which is provided by a third-party system provided by the client. My first thought was to directly call the service and show the results of that call – but the response took too long.
So I decided to make a custom index containing the external data and thus having a great response time. Weiterlesen

Sitecore-Logging auf High-Traffic-Sites

Jeder Sitecore-Entwickler weiss mit Sicherheit, wie man Log-Einträge schreibt. Z.B.

Log.Error("Some error occurred!", typeof(MyClass));

Mit der standard-Sitecore-Konfiguration würde das einen Eintrag im Log des aktuellen Tages machen. Dieser Standardansatz funktioniert gut, solange nicht allzu viel Traffic auf der Site herrscht. Auf hoch frequentierten Sites hingegen, wird die Analyse von Logs sehr schwierig.

Hauptprobleme sind:

  1. Sitecore erzeugt selbst Log-Einträge, die mit applikations-spezifischen Einträgen vermischt werden –> viele Log-Einträge
  2. Die Logging-Konfiguration (z.B.  Ausgabemedien oder Log-Level) können nicht geändert werden ohne Zugang zu den Config-Dateien
  3. Es ist nur schwer möglich, Log-Einträge einem bestimmten Request oder einer bestimmten Session zuzuordnen.

Bestehende Lösungen

In diversen Blog Posts sind bereits verschiedene Wege beschrieben worden, wie die Standard-Sitecore-Logging-Konfiguration verbessert werden kann. Zum Beispiel kann mit einem eigenen log4net Appender und logger ein eigenes Log-File als Ausgabemedium genutzt werden.

Ein weiterer Weg, eigene Log-Einträge von den Sitecore-eigenen Einträgen zu unterscheiden ist, eigene Log-Einträge mit einem Präfix zu versehen. Log4net kann dann mittels Regex-Pattern diese Einträge gesondert in ein eigenes Log schreiben.

Ferner kann die Ausgabe auf andere Medien z.B. in eine SQL-Tabelle die Analyse einfacher machen. John West beschreibt in seinem Post verschiedene Möglichkeiten, dies umzusetzen.

Eigene Log-Einträge von den Sitecore-eigenen Einträgen gesondert zu behandeln ist also möglich. Dies löst aber noch nicht unsere anderen beiden Probleme.

  1. Ist es auch mit eigenem Log-File immer noch schwierig, Log-Einträge einem bestimmten Request zuzuordnen und
  2. Für Anpassungen von Log-Level und Ausgabemedien ist eine Änderung der web.config nötig, was Server-Zugriff voraussetzt.

Dies sind die Gründe, wieso wir uns dafür entschieden haben, einen anderen Ansatz zu wählen.

Unser Ansatz

Die Grundidee ist, die Sitecore-Logging-Funktionen über eine eigene Logger-Klasse von unsrem Code zu entkoppeln. Das heisst konkret, dass wir eigene .Warn(), .Error(), usw. -Methoden implementieren.

 

Logger.Error("Some error occurred!");

Wird eine dieser Methoden aufgerufen, startet unser Logger dynamisch Processors für spezifische Ausgabemedien (ähnlich wie log4net appenders), die zur Laufzeit ein/ausgeschaltet und konfiguriert werden können.

Auf diese Weise können wir die ursprünglichen drei Probleme lösen:

  1. Unsere eigenen Log-Einträge können von denen des Sitecore-Systems getrennt werden, da wir eigene Log-Einträge über unsren eigenen Logger schreiben.
  2. Die Konfiguration von Log-Levels und Ausgabemedien kann zur Laufzeit über das Sitecore-Backend vorgenommen werden.
  3. Durch Implementieren eines Browser-Console-Log, können wir Log Events eines spezifischen Requests direkt zur Browser-Konsole ausgeben via HTTP- Headers. Dazu haben wir das FirePHP  Protokoll in .NET umgesetzt.

Mit diesem Ansatz gewinnen wir viel Flexibilität punkto Logging. Speziell in komplexen Infrastrukturen mit mehreren Servern und ohne direkten Zugang zu Config-Dateien kann dies eine grosse Hilfe beim Analysieren von Problemen sein.

Starter Paket für Sitecore Entwickler

In der Präsentation wird vermittelt, was Sitecore Software Engineers grundlegendes über das CMS wissen sollten, um mit der Entwicklung zu starten.

Nachfolgende Themen werden behandelt:

  • Einrichten
  • Authoring
  • Development
  • Deployment
  • Ressourcen

Haben wir Dein Interesse geweckt für die Sitecore CMS-Entwicklung? Namics hat fortlaufend spannende Stellen im .NET Umfeld in der Schweiz und Deutschland zu besetzen. Wir freuen uns auf Deine Bewerbung!

Type Safe Programming mit Sitecore

Das Ablegen der strukturierten Inhalte in Sitecore erfolgt in vordefinierten Templates. Die Items speichern die nach dem zugeordneten Template strukturierten Informationen ab, welche anschliessend für das Rendern der Webseite verwendet werden können.

Problematik

Im Sitecore Backend wird diese Struktur/Templates für das Editieren der Informationen herangezogen. Dem Programmierer bleibt die Struktur der Templates während der Design Time (Entwicklung) immer verwehrt. Erst zur Runtime sind diese Informationen verfügbar. Dies führt dazu, dass beim kompilieren keine Validierung des Zugriffes auf die Daten erfolgen kann, was z.B. beim Umbenennen oder Typenändern eines Feldes nicht sofort zu einer Exception führt. Weiter muss der Entwickler immer den jeweiligen Feldnamen und Typen kennen/nachschlagen.

Lösung

Extrahieren der gesamten Sitecore Template Struktur zur Entwicklungszeit ins Visual Studio. Dabei gibt es unterschiedliche Varianten wie dies erfolgen kann:

Methode Beschreibung Vorteile Nachteile
dynamic Mit .Net 3.0 wurden dynamische Objekte eingeführt die erst zur Runtime bestimmt werden.
  • sehr einfache Implementation
  • Kein Intellisense zur Design Time
  • Keine Validierung zum Kompilierzeitpunkt
F# Typeprovider F# bietet die Möglichkeit beim Kompilieren dynamisch statische Typen aus externen definitionen zu erstellen
  • F# Klassen lassen sich nahtlos in C# verwenden
  • Voller Funktionsumfang
  • Automatisches Update bei Änderungen
  • Intellisense nur in F# vorhanden
T4 Templates Mittels T4 Templates werden zur Design Time statische Klassen generiert, welche den Zugriff auf die Sitecore Items stark typisiert wrappen
  • Intellisense
  • Validierung zum Kompilierzeitpunkt
  • Manuelles Anstossen des Generiervorganges bei Änderungen (könnte durch PreBuild Action erfolgen)
Project Roslyn Spracherweiterung für C# welche zur Design und Runtime den Zugriff auf die Item Definition in Sitecore sicherstellt
  • Optimale Integration
  • Änderungen im Sitecore sind sofort erkennbar
  • LINQ Funktionalität
  • Sehr komplex
Wir haben uns für die T4 Template Lösung entschieden, da alle aktuellen Codegerneratoren im Visualstudio darauf basieren und es sich um eine bewährte Technologie handelt (Microsoft Entity Framework, SOAP, usw). Um den Zugriff auf Sitecore stark zu kapseln wurden für alle Standardfeldtypen aus Sitecore Helperklassen erstellt die z.B. den Zugriff auf die Url direkt über ein Property möglich machen.

Sitecore Template

Generiertes Interface

Datenzugriff (Razor)

Durch die weitere Integration von Razor als Render Engine kann nun stark typisiert sauberer Render-Code erstellt werden und gänzlich auf den Stringbuilder und dergleichen verzichtet werden.

Durch den Aufbau dieser beiden Verbesserungen konnte das Entwickeln/Debuggen mit Sitecore massiv verbessert und beschleunigt werden.

Sitecore Web.Config aufteilen

Da Sitecore zu Grunde liegend eine ASP.NET Applikation ist, welche  auf IIS läuft, basiert die Grundkonfiguration auf der web.config. Diese Datei wird bei der Installation stark erweitert und verliert somit an Übersichtlichkeit.

Divide and conquer

Durch einfaches Splitting, erreicht die web.config wieder eine Grösse die man gut lesen kann. Beim starten des Worker Process sammelt der IIS alle Configs zusammen.

Ein Nachteil beim Splitting ist, wenn es die Projektanforderung verlangt, dass die ConnectionStrings verschlüsselt werden. Dies funktioniert nur, wenn die ConnectionStrings in der Web.Config bleiben.

Und so wirds gemacht:

<configuration>
 <connectionStrings configSource="App_Config\ConnectionStrings.config" />
 <appSettings configSource="App_Config\AppSettings.config" />
 <sitecore configSource="App_Config\Sitecore.config" />
</configuration>