Mit der Windows Workflow Foundation 4 bekommen Entwickler die Möglichkeit schnell und einfach Workflows als WCF Dienste zu veröffentlichen. Visual Studio 2010 bringt hierzu bereits ein Projekttemplate mit, wodurch das Erstellen einer Workflow Service Anwendung mit nur wenigen Klicks realisiert werden kann.
Zwar besteht auch die Option einen WorkflowService mit einfachen Typen wie Strings, Integers usw. zu erstellen, aber im Rahmen dieses Artikels möchte ich auf den “sauberen” Weg über DataContracts eingehen.
Nachdem das neue Projekt vom Typ Workflow Service Application mit Visual Studio erstellt wurde, muss eine Klasse für den DataContract hinzugefügt werden. Der Workflow in diesem Beispiel soll eine Bestellposition (bestehend aus Produktname und Bestellmenge) weiterverarbeiten und als Ergebnis die berechnete Bestellposition zurückgeben. (Bestehend aus Produktname, Bestellmenge und Gesamtpreis).
Der erstellte DataContract für die Eingangsnachricht (Request) sieht demnach wie folgt aus
[DataContract(
Namespace =
"http://www.dotnet-rocks.de/ServiceTypes/wf4/OrderPositionRequest/2010/03/30")]
public class OrderPositionRequest
{
[DataMember(IsRequired = true)]
public String ProductName { get; set; }
[DataMember(IsRequired = true)]
public int OrderQuantity { get; set; }
}
Das Erstellen von DataContracts ist in WCF4 unverändert im Vergleich zur Vorgängerversion WCF3. Wichtig ist lediglich dass im DataContract Attribut der Namespace des Kontraktes angegeben wird.
Gibt man keinen Namespace für den DataContract an, findet man die altbekannte http://tempuri.org später im WSDL wieder.
Im nächsten Schritt wird der DataContract für die Ausgangsnachricht (Response) definiert
[DataContract(
Namespace =
"http://www.dotnet-rocks.de/ServiceTypes/wf4/OrderPositionRequest/2010/03/30")]
public class OrderPositionResponse
{
public OrderPositionResponse(String productName, int orderQuantity, double totalPrice)
{
this.ProductName = productName;
this.OrderQuantity = orderQuantity;
this.TotalPrice = totalPrice;
}
[DataMember(IsRequired = true)]
public String ProductName { get; set; }
[DataMember(IsRequired = true)]
public int OrderQuantity { get; set; }
[DataMember]
public double TotalPrice { get; set; }
}
Beim anlegen des Projektes hat VS 2010 automatisch eine xamlx Datei angelegt, diese Datei repräsentiert den WorkflowService, der veröffentlicht werden soll. An dieser Stelle möchte ich nicht das vordefinierte Item umbenennen und anpassen, sondern von Grund auf beginnen, daher empfiehlt es sich die xamlx Datei zu löschen und über Add –> New Item–> WCF Workflow Service einen Neuen WorkflowService mit dem Namen “OrderPositionCalculationService” anzulegen.
Ausgehend von diesem neuen WorkflowService, kann nun damit begonnen werden das BusinessRequirement abzubilden. Zunächst sollte auf der ReceiveRequest Activity einige Properties angepasst werden, damit unser späteres WSDL auch korrekt aussieht.
- DisplayName
- Wert: “Receive OrderPosition”
- OperationName
- Wert: “CalculateOrderPosition”
- ServiceContractNamespace
- Wert “{http://www.dotnet-rocks.de/services/wf4/}OrderPositionCalculationService”
- CanCreateInstance
Nachdem die Basiseinstellungen für den Empfang von Nachrichten vorgenommen wurden, muss der Activity noch gesagt werden was sie denn überhaupt empfangen bzw. verarbeiten soll. Hier kommen die Variablen der WF4 wieder ins Spiel, da der gewünschte Service eine Instanz von OrderPositionRequest verarbeiten soll, muss eine neue Variable dieses Typs zum WorkflowService hinzugefügt werden.
Bei dieser Gelegenheit, sollte die data Variable gerade gelöscht werden
Über das Variables Tab des WorkflowDesigners kann dies sehr einfach realisiert werden.
Den Typ der Variable kann man sehr einfach über den Type Browser festlegen wie Abbildung 3 zeigt.
Nachdem die Variable erstellt und konfiguriert wurde, muss auf der Receive Activity noch der Message Typ festgelegt werden. Über einen Klick auf “view message” im WorkflowDesigner öffnet sich das Content Definition Fenster, hier müssen MessageData und Message Type angeben werden.
In MessageData muss die, zuvor erstellte, Variable OrderPositionToCalculate hinterlegt werden. Damit der WCF Service auch den korrekten Typ an den Workflow weitergeben kann muss auch hier nochmals der Typ der Message angegeben werden. (Abbildung 4)
Analog zu Receive Activity muss nun noch die Send Response Activity konfiguriert werden. Auch hier muss zunächst eine WorkflowVariable angelegt werden. Hierbei sind folgende Einstellungen zu verwenden.
- Name
- Wert “CalculatedOrderPosition”
- Variable Type
- Wert “OrderPositionResponse”
Im Anschluss an die Variablendefinition muss auch für die Antwort der Content definiert werden. Hierbei sind die folgenden Werte anzugeben
- Message Data
- Wert “CalculatedOrderPosition”
- Message Type
- Wert “OrderPositionResponse”
An dieser Stelle ist der Rahmen des Workflow Services fertiggestellt. Nun fehlt noch die eigentliche Businesslogik. In diesem Beispiel besteht die gesamte Logik daraus, die Bestellmenge mit dem Preis des Produktes zu multiplizieren und das Ergebnis in die Variable vom Typ OrderPositionResponse zu schreiben.
Dank der BAL (Base Activity Library) der WF4, bietet die Workflow Foundation 4 auch für diese Anforderung eine einfache Lösung an, die Assign Activity.
Im WorkflowDesigner positioniert man die Assign Activity genau zwischen den Receive und Send Activities.
Die Assign Activity kann recht einfach konfiguriert werden um die Anforderungen zu erfüllen, um den Rahmen des Artikels nicht zu sprengen, gehe ich in diesem Workflow immer von einem Produktpreis 5.95 Euro aus.
Die Assign Activity wird folgendermaßen konfiguriert
CalculatedOrderPosition = new OrderPositionResponse(OrderPositionToCalculate.ProductName, OrderPositionToCalculate.OrderQuantity, OrderPositionToCalculate.OrderQuantity * 5.95)
Just hit F5
Debuggen und Testen kann man seinen WorkflowService ganz einfach durch F5 oder den Befehl Debug –> Start Debugging. Visual Studio 2010 startet automatisch den WCF Test Client und hostet den zuvor erstellten Service darin. Im WCF Test Client kann man durch die Methoden des WCF-Services browsen und die gewünschte Methode invoken.
In der letzten Abbildung sieht man das Ergebnis der Arbeit, im WCF Test Client kann man die Methode CalculateOrderPosition invoken und eine Instanz des Typs OrderPositionRequest übergeben.
Das unten dargestellte Ergebnis belegt, dass der entwickelte WorkflowService alle Anforderungen erfüllt und somit ist der erste WorkflowService auf Basis der WF4 entwickelt.