Nachdem ich mich jetzt endlich etwas mit den neuen SharePoint 2013 Workflows beschäftigen konnte, möchte ich hier meine Erfahrungen festhalten. Auch damit ich selbst etwas zum Nachschlagen habe 😉
Im ersten Teil soll es darum gehen, wie man mit der neuen Aktion Call HTTP Web Service Daten aus SharePoint abfragen kann. Selbstverständlich kann man damit jeden beliebigen Webservice abfragen, aber mir ging es ganz speziell um Daten aus SharePoint. Prinzipiell kommt man damit an die Daten aus jeder beliebigen SharePoint-Website, auch wenn sie sich in einer anderen Farm befinden. Voraussetzung dafür ist, daß der Benutzer dazu berechtigt ist (und natürlich daß der Webservice erreichbar ist).
Testumgebung
Für den Test habe ich ein einfaches Szenario aufgebaut: innerhalb einer Website gibt es eine Parent List und eine Child List, die über ein Nachschlagefeld mit der Parent List verbunden ist. Die Parent List hat ein zusätzliches Zahlenfeld Child Count. Ein Workflow auf der Parent List soll jetzt alle zugehörigen Elemente der Child List finden und deren Anzahl beim Parent in Child Count eintragen. Zur Verdeutlichung hier die Parent List:

Und die Child List:

Workflow erstellen
Wir öffnen jetzt die Website in SharePoint Designer 2013 und erstellen einen neuen Listenworkflow für die Parent List. Die Vorgehensweise dazu ist dieselbe wie in 2010, aber beim Anlegen muß darauf geachtet werden, daß SharePoint 2013 Workflow ausgewählt ist. Nur dann stehen die neuen Funktionen auch zur Verfügung:

Service-URL
Im Workflow brauchen wir zunächst die Adresse des Services, den wir für die Abfrage der verknüpften Elemente verwenden wollen. Wir nehmen dafür den in SharePoint 2013 neuen REST-Service, der unter der Adresse <Website>/_api zur Verfügung steht. Der Platzhalter <Website> steht hierbei für die absolute URL der Website, also ungefähr http://sharepoint.firma.tld/Sites/Site1. Wenn es sich wie in unserem Beispiel um die aktuelle Website handelt, kann man dafür die vordefinierte Variable Workflowkontext: Aktuelle Website-URL verwenden.
Da wir hier die Daten einer ganz bestimmten Liste möchten, hängen wir an die URL noch folgendes an: /_api/lists/GetByTitle(‚Child List‘)/Items. Da wir uns im ersten Schritt nur für die ID und den Titel der verknüpften Elemente interessieren, teilen wir der API das mit: ?$select=Id,Title.
Das wichtigste ist aber der Filter, weil wir nur die Elemente haben möchten, die zu unserem aktuellen Element der Parent List gehören. Prinzipiell geht das so: $filter=<LookupField> eq <ID>. <LookupField> ist der interne Name des Nachschlagefelds, <ID> ist die ID des aktuellen Parent-Elements und eq steht für equals also zu deutsch ist gleich. Achtung: damit der Filter funktioniert, muß man das Feld auch beim $select-Parameter angeben und dort mit dem Suffix Id (also ParentId). Zum Ausprobieren wie die Abfrage genau aussehen muß und wie die Felder heißen, empfehle ich einen Test im Browser. Wie das geht, wird weiter unten unter Exkurs erklärt.
Hier nochmal zusammengefaßt die gesamte aufzurufende URL, die wir einer Variablen REST-URL zuweisen. Da man den Text wegen der Nachschlageinformationen ohnehin nicht kopieren kann hier nur als Screenshot:

Request Header
Damit der REST-Service die Daten in einem Format liefert, das vom Workflow verarbeitet werden kann, müssen für die Abfrage sogenannte Request Header definiert werden. Die Header Accept und Content-Type müssen beide auf den Wert application/json;odata=verbose gesetzt werden. Im Workflow geschieht das durch den ebenfalls neuen Variablentyp Dictionary.
Wir legen also eine neue Dictionary-Variable RequestHeaders an und verwenden die Aktion Build Dictionary um die beiden Header einzutragen:

Exkurs: SharePoint 2013 REST API
Man kann den REST-Service zum Ausprobieren auch jederzeit einfach im Browser aufrufen. Der Service liefert XML zurück, das der Internet Explorer als Feed interpretiert. Wie man ihn dazu bringen kann die rohen XML-Daten anzuzeigen, habe ich hier beschrieben.
Wenn man sich die vom Service gelieferten Json-Daten im Browser anschauen möchte, wird es schon schwieriger, weil man wie oben für den Workflow beschrieben, die an den Server gesendeten Header modifizieren muß. Beim Internet Explorer habe ich keinen Weg gefunden das zu erreichen. Ich habe dann einige Plugins für Firefox getestet, aber leider auch ohne Erfolg. Fündig geworden bin ich dann mit Google Chrome und dem Plugin Change HTTP Request Header. Wenn man damit die Header wie oben gezeigt modifiziert, kann man sich das Ergebnis einer REST-Abfrage auch im Json-Format anzeigen lassen. Wer es etwas schöner formatiert haben möchte, kopiert es in den Json Parser Online.
Ein guter Einstiegspunkt in die offizielle Dokumentation von Microsoft findet sich hier: Get startet with the SharePoint 2013 REST service.
Call http Web Service
Jetzt aber weiter im Workflow. Nachdem wir jetzt die URL des Services und die notwendigen Header haben, fügen wir eine Call HTTP Web Service Aktion ein. Für den ersten Parameter verwenden wir einfach unsere vorher festgelegte Variable und belassen die HTTP-Methode bei GET:

Von den restlichen Parametern der Aktion setzen wir nur den ResponseContent (das Ergebnis der Abfrage) auf eine gleichnamige Dictionary-Variable und den ResponseCode auf eine gleichnamige String-Variable. Der Response Code gibt Auskunft über den Erfolg der Abfrage und kann zur weiteren Steuerung des Workflows verwendet werden. Er lautet OK, wenn die Abfrage syntaktisch in Ordnung war. Natürlich kann die Abfrage trotzdem logische Fehler enthalten, so daß z.B. der Filter nicht wie erwartet funktioniert, aber das muß separat festgestellt werden. Alle anderen Parameter interessieren uns hier nicht.
Achtung: der aufmerksame Leser fragt sich jetzt wahrscheinlich was mit unserer Variablen für die Request Header passiert. Diese muß der Workflowaktion auf anderem Wege zugewiesen werden und zwar über das Eigenschaften-Fenster, das man bei jeder Workflowaktion über ihr Menü erreichen kann. Das Menü findet man, wenn man mit der Maus über die Aktion fährt und dann auf den DropDown-Pfeil ganz rechts klickt. Innerhalb des Fensters kann man jetzt auch die Variable für die Request Header setzen (3. Punkt von oben):

Warum das an dieser Stelle so umständlich zu handhaben ist, kann ich nicht sagen, halte es aber für einen Bug. Oder zumindest für ein Versäumnis.
Ergebnisverarbeitung
Das Ergebnis der Abfrage haben wir jetzt in einer Dictionary-Variablen ResponseContent. Hier soll nur gezeigt werden, wie man die Anzahl der gefundenen Elemente ermitteln und in ein Feld des Parentelements schreiben kann. Zunächst holen wir uns ein Subset des Ergebnisses in eine weitere Dictionary-Variable ResultItems. Dazu verwenden wir die Aktion Get an Item from a Dictionary und geben für den Parameter item by name or path den Wert d/results an. Mit der Aktion Count Items in a Dictionary bekommen wir jetzt die Anzahl der gefundenen Elemente in eine Integer-Variable ItemCount. Mit der Aktion Set Field in Current Item lassen wir uns diesen Wert jetzt noch ins aktuelle Parentelement ausgeben.
Hier nochmal der gesamte Workflow zusammengefaßt:

Im zweiten Teil wird gezeigt, was man mit dem Ergebnis der Abfrage noch anstellen kann. Dort geht es dann um eine Schleife, die alle gefundenen Elemente durchläuft.