Using the SendActivity Activity
The SendActivity activity is used to model a client-side synchronous operation invoke defined on a contract that is implemented by a service that uses Windows Communication Foundation (WCF).
Generating Code for Service Contracts
To use a SendActivity activity within a workflow, you need the contract interfaces and the client-side configuration of the endpoints associated with those contracts. One way to achieve this is to use the Svcutil.exe command-line tool to accomplish this. For example, if a service is running with a discoverable endpoint located at http://localhost:8888/MyService.svc, you can generate the necessary code needed by the SendActivity activity using the syntax:
The Svcutil.exe tool will generate an application configuration file you can use in your application that defines the specific endpoint and bindings needed to use the service. The second file that is generated contains a proxy class and the actual contract interfaces. The contract definitions are needed by the SendActivity activity for service discovery. These two files should be added to your workflow project so that the SendActivity activity can use the information in them.
If you have access to the contract interfaces, you can add them directly to your project without having to use the Svcutil.exe tool, making sure to also add the proper client endpoints configuration in the application configuration file.
Invoking Service Methods
A SendActivity activity needs certain information to successfully connect to and invoke operations on a service contract: a ChannelToken and operation information.
Specifying the ChannelToken for a SendActivity Activity
A WCF endpoint contains information regarding the contract name, the contract binding, security information, and the address. This information is entered in your application configuration file and can be generated using the Svcutil.exe tool mentioned in the previous section. For example, the client node within an application configuration file for a service listening at the address http://localhost:8888/MyService.svc would appear as follows:
<client> <endpoint address="http://localhost:8888/MyService.svc" binding="customBinding" bindingConfiguration="WSHttpContextBinding_MyServiceContract" contract="MyService.localhost.MyServiceContract" name="WSHttpContextBinding_MyServiceContract"> <identity> <userPrincipalName value="firstname.lastname@example.org" /> </identity> </endpoint> </client>
When creating a SendActivity activity, you create a ChannelToken object specifying the channel name by setting System.Workflow.Activities.ChannelToken.Name, the scope of the channel by setting System.Workflow.Activities.ChannelToken.OwnerActivityName, and the client endpoint by setting System.Workflow.Activities.ChannelToken.EndpointName property of the ChannelToken object. You then associate the ChannelToken object with a SendActivity instance using the ChannelToken property. The following code shows how to create a SendActivity activity and a ChannelToken object, and also shows how to associate the ChannelToken with the SendActivity activity using the information from the application configuration shown earlier.
SendActivity sendActivity1 = new SendActivity(); ChannelToken channel1 = new ChannelToken(); channel1.EndpointName = "WSHttpContextBinding_MyServiceContract"; channel1.Name = "WSHttpContextBinding_MyServiceContract"; channel1.OwnerActivityName = "Workflow1"; this.sendActivity1.ChannelToken = channel1; this.sendActivity1.Name = "sendActivity1";
Specifying the Operation Information for a SendActivity Activity
A SendActivity activity calls a single operation defined within a single contract. To accomplish this, the SendActivity uses a TypedOperationInfo object that contains information about the data type for the contract as well as the name of the operation to invoke. The ContractType property of the TypedOperationInfo class refers to the contract interface type. The Name property accessed through the TypedOperationInfo class refers to the name of the operation to call within that type.
System.Workflow.Activities.TypedOperationInfo typedoperationinfo1 = new System.Workflow.Activities.TypedOperationInfo(); typedoperationinfo1.ContractType = typeof(MyServiceContractClient.localhost.MyServiceContract); typedoperationinfo1.Name = "DoWork"; typedoperationinfo1.PrincipalPermissionName = ""; typedoperationinfo1.PrincipalPermissionRole = ""; this.sendActivity1.ServiceOperationInfo = typedoperationinfo1;