Hinzufügen eigener Felder zur Suchseite eines SharePoint 2013 Search Centers

05. August 2013
SharePoint Logo

SharePoint 2013 bietet im Vergleich zu seinen Vorgängern mehr und einfachere Möglichkeiten, Anpassungen am Frontend vorzunehmen. Wer bereits in SharePoint 2010 mit xslt-Templates Erfahrungen gesammelt hat, weiß, dass Anpassungen an Templates nicht immer leicht von der Hand gingen.

Da in SharePoint 2013 JavaScript zum Rendern der Suchergebnisse benutzt wird, kann man den ganzen Vorgang im Browser debuggen. Man ist also in der Lage „live“ zu erfahren, warum manche Sachen nicht so gerendert werden, wie man will, ohne dass man massiv Log-Ausgaben einbauen muss oder mit Visual Studio debuggt und dabei ein SharePoint zum Stillstand bringt.

Was haben wir vor?

Ziel dieses Blogbeitrags ist, zu erklären, wie man seine Suchergebnisse im Search Center mit beliebigen Feldinhalten, die bereits vom SharePoint erfasst wurden, anreichert und somit ein Search Center mit aussagekräftigeren Ergebnissen erhält.

Damit man sich darunter etwas vorstellen kann, hier ein Bild vom Ergebnis; unter dem Titel wird der Dateiname angezeigt, was es einfacher macht, zu schauen, ob man bereits lokal eine Kopie der Datei hat. Über Sinn, Zweck und Schönheit des Ganzen lässt sich streiten, aber als Anschauungsbeispiel genügt dieses Beispiel vollkommen.

Suchergebnis mit Dateinamen

Was müssen wir anpassen?

Um zu verstehen, welche Templates wir anfassen müssen, fangen wir mit einer kleinen Übersicht über die Struktur der Display Templates der Suchergebnisse an.

Search Results und Search Result Items

Was hier durch die farbigen Markierungen gezeigt wird, sind

  • Türkis: Äußere Result Story, ein Wrapper um alle einzelnen Elemente

  • Rot: Ein Ergebnis, also ein gefundenes Dokument in unserem Fall und genau der Teil, den wir anpassen wollen

Um unsere Anpassungen vorzunehmen, öffnen wir mit dem SharePoint Designer unser Search Center und navigieren in den Pfad

_catalogs/masterpage/DisplayTemplates/Search

Und werden gleiche von einer Reihe von html und js Dateien begrüßt. Die Datei, die uns hier interessiert, ist die

Item_CommonItem_Body.html

Diese ist das Template, welches verwendet wird, um ein einzelnes Suchergebnis zu rendern (der rote Bereich im vorrangehenden Bild).

Wenn wir diese Datei mit Rechtsklick→„Edit File in Advanced Mode“ öffnen, können wir bereits Anpassungen vornehmen. Wenn wir zum Beispiel unter die Zeile mit dem Eintrag

<div id="_#= $htmlEncode(id + Srch.U.Ids.body) =#_" class="ms-srch-item-body" onclick="_#= showHoverPanelCallback =#_">

(etwa Zeile 62) ein

<div>Hallo SharePoint!<br></div>

schreiben und unsere Suchseite neu laden, sehen wir

Hello SharePoint!

Wir sind also schon mal richtig!

Was müssen wir hier tun?

Wenn man über die Datei schaut, wird die grundlegende Template Syntax schnell klar:

  • JavaScript-Blöcke werden mit „<!--#_“ begonnen und mit „#-->“ geschlossen
  • Variablen aus den JavaScript-Blöcken können direkt in html Code ausgegeben werden, indem sie mit „_#=“ und „=#_“ umschlossen werden
  • Die Mapped Properties sind an „ctx.CurrentItem“ zu finden. Im Code finden sich Beispiel, wie ctx.CurrentItem.Title, ctx.CurrentItem.Path, etc.

Um unseren Dateinamen anzuzeigen, entfernen wir erst unseren „Hello SharePoint!“ Eintrag von eben und gehen zu Zeile 78, die Stelle, an der das h3 vom Ergebnistitel geschlossen wird. Unter das „</h3>“ fügen wir nun folgendes ein:

<!--#_
      if (ctx.CurrentItem.Filename) {
_#-->
        <h4 class="ms-srch-ellipsis">
            _#= ctx.CurrentItem.Filename =#_
        </h4>
<!--#_
      }
_#-->

Das Snippet sollte soweit selbstklärend sein, was hier aber auffällt und was man beachten sollte, ist, dass jeder JavaScript-Teil, der zur Renderlogik gehört und somit nicht ins Frontend gegeben werden soll, in einem Codeblock steht.

Nach dem Speichern des Templates und dem Reload der Seite sehen wir immer noch keine Änderung.

Warum?

Ganz einfach: Die Property „Filename“ gehört nicht zu dem Standard-Satz von Properties, die bei einer Suche angefordert und zurückgeliefert werden. Somit kommt sie im Moment nicht im Result an.

Wie fordern wir beim Suchen eigene Properties an?

Hierfür gibt es im Kopf des Templates den Eintrag

<mso:ManagedPropertyMapping msdt:dt="string">

An dieser Stelle werden die angeforderten Properties angegeben. Leider ist dies jedoch die Stelle im Blogbeitrag, in der wir auf Tricks zurückgreifen müssen. Nach Dokumentation sollte es reichen, an dieser Stelle oder an der gleichen Stelle im Template „Item_Default.html“ die Property hinzufügen, um die Properties zurückgeliefert zu bekommen. Leider trifft dies nur solange zu, wie man auch nur dieses eine Template rendert – entweder per Regel im SharePoint oder per Konfiguration am Result Webpart. Da wir aber verschiedene Templates für die einzelnen Ergebnisse nutzen  wollen, ist das hier keine grundlegene Lösung.

Die gewünschten Properties lassen sich aber auch auf andere Art und Weise hinzufügen. Man editiert die Seite und fügt ein ScriptEditorWebPart hinzu, klickt auf „Edit Snippet“ und fügt folgendes Script ein:

<script type="text/javascript">
//<![CDATA[

/*
Injects additional managed properties to search queries
due to a bug with the ResultScriptWebPart where
Managed Properties are not returned for the Display Templates:
http://social.msdn.microsoft.com/Forums/en-US/sharepointsearch/thread/f53c87d0-af81-445c-8338-1bfea6ca780e

Add Manage Property names to newProps array.
*/
function insertSelectedProperties() {
  var newProps = ['Filename'],
      groups = Srch.ScriptApplicationManager.get_current().queryGroups;

  for (var x in groups) {
    var group = groups[x],
        props = group.dataProvider.get_selectedProperties();

    Array.forEach(newProps, function(prop) {
      if (!Array.contains(props, prop)) {
        props.push(prop);
      }
    });

    group.dataProvider.set_selectedProperties(props);
  }
}
Srch.ScriptApplicationManager.get_current().add_preLoad(insertSelectedProperties);

/*
This is a bit of a hack as it does a second query on load if there's a search query
string value. Could be removed if we can find a better event to hook insertSelectedProperties into.
*/
function doSelectedPropertiesSearch() {
  var groups = Srch.ScriptApplicationManager.get_current().queryGroups;

  for (var x in groups) {
    var group = groups[x];

    Array.forEach(group.searchBoxes, function(box) {
      if (box.get_currentTerm() != '') {
        box.search(box.get_currentTerm());
      }
    });
  }
}
Srch.ScriptApplicationManager.get_current().add_postLoad(doSelectedPropertiesSearch);

//]]>
</script>

 (Quelle: http://social.msdn.microsoft.com/Forums/de-DE/f53c87d0-af81-445c-8338-1bfea6ca780e/managed-properties-in-display-templates)

Speichern, Seite einchecken, Seite publishen und die Suchseite neu laden und wir sehen sehen unsere lang ersehnte Property. :)

Search Result mit Filename

Fazit

Wenn wir den Workaround am Ende einmal ignorieren, lassen sich Suchergebnisse relativ einfach um neue Eigenschaften erweitern, was viele Möglichkeiten bietet, um Nutzern mehr Informationen anzubieten als das Standard Search Center. Zudem lassen sich die Templates durch clientseitige Debug-Möglichkeiten schneller und einfacher entwickeln.

Neuen Kommentar schreiben