Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
In diesem Beispiel werden zwei wichtige Features der Workflowdienste veranschaulicht:
Die "Workflow zuerst"-Methode zum Erstellen von Diensten
Es gibt zwei Methoden zum Erstellen von Diensten mit Workflows. Eine ist das Erstellen mit "Vertrag zuerst", wobei der Vertrag bereits vorhanden ist und der Workflow den Vertrag implementiert. Die andere ist "Workflow zuerst", wobei der Vertrag beim Erstellen des Workflows erstellt wird. Der Workflow-Designer fungiert dabei praktisch als Vertrags-Designer. In diesem Beispiel wird beim Erstellen des Workflows der Rechnervertrag erstellt.
In diesem Beispiel wird das Markup für "Workflow zuerst" in der Datei "SequentialCalculatorService.xoml" implementiert. Vergleichen Sie dies zum besseren Verständnis des Programmiermodells der "Workflow zuerst"-Programmierung mit dem Markup für andere Workflowbeispiele.
Im folgenden Beispielcode wird das Markup für die Receive-Aktivität im Beispiel dargestellt.<ns0:ReceiveActivity x:Name="ReceiveAdd" OperationValidation="ValidateOwner" CanCreateInstance="True"> <ns0:ReceiveActivity.ServiceOperationInfo> <ns0:OperationInfo PrincipalPermissionRole="Administrators" Name="Add" ContractName="ICalculator"> <ns0:OperationInfo.Parameters> <ns0:OperationParameterInfo Attributes="In" ParameterType="{x:Type p15:Int32}" Name="value" Position="0" xmlns:p15="clr-namespace:System;Assembly=mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" /> <ns0:OperationParameterInfo Attributes="Out" ParameterType="{x:Type p15:Int32}" Name="returnValue" Position="1" xmlns:p15="clr-namespace:System;Assembly=mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" /> </ns0:OperationInfo.Parameters> </ns0:OperationInfo> </ns0:ReceiveActivity.ServiceOperationInfo> <ns0:ReceiveActivity.ParameterBindings> <WorkflowParameterBinding ParameterName="value"> <WorkflowParameterBinding.Value> <ActivityBind Name="SequentialCalculatorService" Path="inputValue" /> </WorkflowParameterBinding.Value> </WorkflowParameterBinding> <WorkflowParameterBinding ParameterName="returnValue"> <WorkflowParameterBinding.Value> <ActivityBind Name="SequentialCalculatorService" Path="currentValue" /> </WorkflowParameterBinding.Value> </WorkflowParameterBinding> </ns0:ReceiveActivity.ParameterBindings> <CodeActivity x:Name="DoAdd" ExecuteCode="Add" /> </ns0:ReceiveActivity>Die Receive-Aktivität enthält keinen Verweis auf einen externen Vertragstyp, und der Vertrag wird in der Receive-Aktivität selbst definiert. Der
OperationInfo-Block in der Receive-Aktivität beschreibt sowohl den Vertragsnamen als auch den Vorgangsnamen. Dies sind Literalzeichenfolgen, die keinen Verweis auf einen Typ enthalten, der den Vertrag definiert.
Wenn Sie das Beispiel ausführen, verwendet der Workflowdiensthost diese Definition zum Erstellen einer Dienstbeschreibung. Verwenden Sie zum Erstellen eines Dienstclients hierfür ServiceModel Metadata Utility Tool (Svcutil.exe).Sicherheit in Workflowdiensten
Workflowdienste stellen zwei Ebenen der Sicherheit für den Dienst bereit. In der ersten Ebene geben Sie für einen Vorgang Prinzipberechtigungssicherheit an. Die Dienstlaufzeit überprüft die Berechtigung vor dem Zustellen der Nachricht an den Workflow. Wenn die Nachricht die Prinzipberechtigungssicherheit nicht erfüllt, wird die Nachricht nicht an den Workflow zugestellt. Die zweite Ebene ist die "Vorgangsvalidierungsbedingung", die Sie einer Receive-Aktivität zuweisen können. Die Vorgangsvalidierungsbedingung wird ausgeführt, wenn die Receive-Aktivität die Nachricht empfängt. Wenn die Nachricht die Vorgangsvalidierungsbedingung nicht erfüllt, wird ein Fehler an den Client gesendet, die Nachricht wird gelöscht, und der Workflow ist fehlerhaft.
Das PrincipalPermissionRole-Attribut im OperationInfo-Element gibt an, dass nur Benutzer in der Administratorgruppe diesen Vorgang aufrufen dürfen.
Das OperationValidation-Attribut in der Receive-Aktivität zeigt auf den Codehandler, der als Validierungsbedingung ausgeführt werden soll. In diesem Beispiel können nur Benutzer in der Administratorgruppe den ersten Vorgang aufrufen, da das PrincipalPermissionRole-Attribut in der ersten Receive-Aktivität festgelegt ist. In diesem Workflow verfügt die Receive-AktivitätReceiveAddüber die Eigenschaft CanCreateInstance. Diese ist auf true festgelegt. Dies bedeutet, dass eine Instanz dieses Diensts erstellt wird, wenn der Add-Vorgang von einem Benutzer in der Administratorgruppe aufgerufen wird.
In den folgenden Receive-Vorgängen stellt die OperationValidation-Bedingung sicher, dass es sich bei dem Prinzipal, der den Vorgang aufruft, um den Prinzipal handelt, der die Instanz erstellt hat. In diesem Szenario kann nur die Person, die die Instanz initiiert hat, weitere Nachrichten senden. Im folgenden Beispiel wird der Code für die OperationValidation-Bedingung dargestellt, die dies ausführt.private void ValidateOwner(object sender, OperationValidationEventArgs e) { if (string.IsNullOrEmpty(owner)) { owner = ExtractCallerName(e.ClaimSets); e.IsValid = true; Console.WriteLine("Owner: " + owner); } if (owner.Equals(ExtractCallerName(e.ClaimSets))) e.IsValid = true; } private string ExtractCallerName(ReadOnlyCollection<ClaimSet> claimSets) { string owner = string.Empty; foreach (ClaimSet claims in claimSets) { foreach (Claim claim in claims) { if (claim.ClaimType.Equals(ClaimTypes.Name) && claim.Right.Equals(Rights.PossessProperty)) { owner = claim.Resource.ToString(); break; } } } return owner; }Die angezeigte
ValidateOwner-Methode stellt Anspruchssätze als Teil desOperationValidationEventArgs-Arguments bereit. Mithilfe dieser Anspruchssätze wird die Nachrichtenvalidierung abgeschlossen. Beachten Sie, dass die tatsächlichen Nachrichtentextparameter an diesem Punkt noch nicht verfügbar sind. DieExtractCallerName-Methode extrahiert den Aufrufernamen aus dem Name-Anspruch und speichert ihn. In folgenden Anforderungen wird der Aufrufername mit dem Name-Anspruch der eingehenden Nachricht verglichen, um sicherzustellen, dass die Person, die die erste Nachricht gesendet (und die Instanz erstellt) hat, die gleiche Person wie der Absender der folgenden Nachricht ist.
Tipp
Zum Erstellen und Ausführen dieses Beispiels muss .NET Framework, Version 3.5 installiert sein. Zum Öffnen des Projekts und der Projektmappendateien ist Visual Studio 2008 erforderlich.
So richten Sie das Projekt ein, erstellen es und führen es aus
Führen Sie die Setupanweisungen in One-time Setup Procedure for Windows Communication Foundation Samples aus.
Führen Sie das Skript CreateStores.cmd im Thema One-Time Setup Procedure for the Windows Communication Foundation Samples aus.
Erstellen Sie die Projektmappe.
Führen Sie das Beispiel als Benutzer der Administratorgruppe aus. Starten Sie zuerst die ausführbare Datei für den Dienst und dann die ausführbare Datei für den Client. Wenn Sie Windows Vista verwenden, klicken Sie mit der rechten Maustaste auf die ausführbare Datei, und klicken Sie dann auf Als Administrator ausführen. Das Beispiel wird bis zum Abschluss ausgeführt.
Versuchen Sie, das Beispiel mit einer anderen Benutzeridentität auszuführen (verwenden Sie hierzu den Befehl Ausführen als). Wenn die Identität nicht zur Administratorgruppe gehört, gibt der Dienst einen Fehler zurück.
So führen Sie das Beispiel auf separaten Computern aus
Bearbeiten die Sie die Konfigurationsdateien des Diensts und des Clients, und stellen Sie sicher, dass Sie den Servernamen in die Endpunktadresse ändern. Ändern Sie den Servernamen von
localhostin den Namen des Computers, auf dem der Dienst ausgeführt wird.Der Dienst verwendet Port 8888, daher müssen Sie diesen Port in der Firewall öffnen. Klicken Sie in der Windows-Systemsteuerung auf Windows-Firewall. Klicken Sie auf Port hinzufügen, und fügen Sie dann Port 8888 hinzu. Sie können den Dienst auch über den Standardport ausführen. Entfernen Sie hierzu :8888 aus der Endpunktadresse.
Bearbeiten Sie die Clientkonfigurationsdatei, und fügen Sie das folgende Element als untergeordnetes Element des
<endpoint>-Elements hinzu.<identity> <UserPrincipalName value=”*@<Domain Name in which your server is running” /> </identity>Starten Sie zum Ermitteln des Domänennamens den Dienst auf dem Computer, auf dem Sie ihn ausführen möchten. Führen Sie in einem Eingabeaufforderungsfenster auf dem anderen Computer den folgenden Befehl aus.
svcutil.exe http://<serverName>:8888/servicehost/Calculator.svcDieser Befehl generiert eine CS-Datei und eine output.config-Datei. Kopieren Sie im
<endpoint>-Element der Konfigurationsdatei das<identity>-Element in die Clientkonfigurationsdatei.