Task 1: Create the Workflow Service

Download sample

In this task, you create a basic state machine workflow service that implements a Windows Communication Foundation (WCF) contract and persists the state information of the service to a SQL database. You will do this through the contract-first authoring style.

Note

This workflow service will be used in the remaining exercises in this tutorial.

Note

When the Visual Studio workflow designer is used to create or manage workflow services, it sometimes produces spurious validation errors. If you are able to successfully build your project, ignore the validation errors.

To set up the workflow service and define the contract

  1. Open Visual Studio 2008, click File, and select New and then Project.

  2. In the New Project dialog box, under WCF, select the State Machine Workflow Service Library template.

  3. Name your project WorkflowServiceTutorial and click OK.

    Visual Studio 2008 generates the following files for your workflow service: an App.config file to store configuration settings using the same schema that is used for WCF services, a source file that contains a contract definition, and the workflow class source files that define the designer code and the implementation code for your workflow.

    The template creates a state machine workflow with two StateActivity activities. The first StateActivity activity, named Workflow1InitialState, contains an EventDrivenActivity activity that itself contains a ReceiveActivity activity followed by a SetStateActivity activity. The SetStateActivity activity has its TargetStateName property set to the name of the other StateActivity activity in the state machine workflow.

    The ReceiveActivity type itself derives from SequenceActivity and, as such, can contain multiple child activities that execute in sequential order. The implementation of a ReceiveActivity activity parallels that of implementing an operation on a standard WCF service, but instead of implementing your code in the body of a method, you will implement the actions through WF activities.

    The ReceiveActivity activities in this tutorial implement several new operations defined in IWorkflow1.cs (or IWorkflow1.vb if you created a Visual Basic solution). These are request/response operations; therefore, the client will receive a message back from the service.

    Because you are using a WCF contract that is already provided, this is known as a contract-first style of authoring a workflow service. If you want to create a new contract programmatically, see How to: Implement a Windows Communication Foundation Contract Operation.

  4. Because you are going to define new operations on your interface, open IWorkflow1.cs (or IWorkflow1.vb if you created a Visual Basic solution) and replace the existing interface definition with code from the following example:

    <ServiceContract()> _
    Public Interface IWorkflow1
    
        <OperationContract()> _
        Sub StartupService()
    
        <OperationContract()> _
        Function Add(ByVal n1 As Integer) As Integer
    
        <OperationContract()> _
        Function Subtract(ByVal n1 As Integer) As Integer
    
        <OperationContract()> _
        Function Multiply(ByVal n1 As Integer) As Integer
    
        <OperationContract()> _
        Function Divide(ByVal n1 As Integer) As Integer
    
        <OperationContract()> _
        Sub ShutdownService()
    
    End Interface
    
    [ServiceContract]
    public interface IWorkflow1
    {
    
        [OperationContract]
        void StartupService();
    
        [OperationContract]
        int Add(int n1);
    
        [OperationContract]
        int Subtract(int n1);
    
        [OperationContract]
        int Multiply(int n1);
    
        [OperationContract]
        int Divide(int n1);
    
        [OperationContract]
        void ShutdownService();
    }
    

To implement the service contract

  1. If the workflow designer is not visible, open the designer by right-clicking on Workflow1.cs (or Workflow1.vb if you created a Visual Basic solution) and select View Designer.

  2. Drag a StateActivity activity into your state machine workflow. Rename it OperationsState.

  3. Rename stateActivity1 to FinalState.

    Note

    When you rename this activity, it is no longer flagged as the completed state for the workflow; therefore, right-click FinalState in the workflow designer and select Set as Completed State.

  4. In the StateActivity activity named Workflow1InitialState, select eventDrivenActivity1 and rename it to WaitToStartService.

  5. Double-click WaitToStartService to expand it. A ReceiveActivity activity has already been set as a child activity of WaitToStartService.

  6. Select receiveActivity1 and in the Properties pane, under ServiceOperationInfo, click the ellipsis to open the Choose Operation dialog box.

  7. Select StartupService and click OK.

  8. In the Properties pane, under CanCreateInstance, ensure that True is selected in the drop-down menu. This means that an instance of the workflow will be created when the StartupService operation is invoked. The default value for this property is set to False, and if a context ID had not already been established between the client and the service upon operation invocation, then the client would receive the following message:

    There is no context attached to incoming message for the service and the current operation is not marked with "CanCreateInstance = true". In order to communicate with this service check whether the incoming binding supports the context protocol and has a valid context initialized.
    
  9. In the Workflow1InitialState design view, select setStateActivity1.

  10. In the Properties pane, change the name for the TargetStateName property from stateActivity1 to OperationsState.

    Navigate back to the main workflow designer view. There should now be a connection between Workflow1InitialState and OperationsState.

  11. Drag and drop five EventDrivenActivity activities into the OperationsState StateActivity activity and name them WaitToAdd, WaitToSubtract, WaitToMultiply, WaitToDivide, and WaitToEndService.

  12. Double-click WaitToAdd to expand it.

  13. Drag and drop a ReceiveActivity activity inside WaitToAdd.

  14. In the Properties pane, under ServiceOperationInfo, click the ellipsis to open the Choose Operation dialog box.

  15. Select Add and click OK.

  16. Drag and drop a CodeActivity activity inside the ReceiveActivity activity.

  17. In the Properties pane, click the Events button.

  18. Double-click the Code activity to auto-generate an event handler method for the ExecuteCode event. This opens Workflow1.cs (or Workflow1.vb if you created a Visual Basic solution).

  19. In Workflow1.cs (or Workflow1.vb if you created a Visual Basic solution) change the variable declarations for returnValue and inputValue, which were created by the template, to the following:

    Public class Workflow1
        Inherits StateMachineWorkflowActivity
    
        Public returnValue as Int32
        Public inputValue as Int32
    
        Private Sub codeActivity1_ExecuteCode(ByVal sender As System.Object, ByVal e As System.EventArgs)
    
        End Sub
    End Class
    
    public sealed partial class Workflow1 : StateMachineWorkflowActivity
    {
        public Workflow1()
        {
            InitializeComponent();
        }
    
        public int returnValue = default(int);
        public int inputValue = default(int);
    
        private void codeActivity1_ExecuteCode(object sender, EventArgs e)
        {
    
        }
    }
    
  20. Navigate to the event handler for ExecuteCode.

    In the body of the event handler, assign returnValue the following value:

        Private Sub codeActivity1_ExecuteCode(ByVal sender As System.Object, ByVal e As System.EventArgs)
            returnValue += inputValue
        End Sub
    
        private void codeActivity1_ExecuteCode(object sender, EventArgs e)
        {
            returnValue += inputValue;
        }
    
  21. Switch back to the workflow designer by selecting View Designer from the View menu. Click the Add ReceiveActivity activity to select it, and in the Properties pane, bind the n1 and (ReturnValue) parameters to the inputValue and returnValue workflow member variables. To bind a parameter, click the ellipsis button to the right of the property name and then select the value to bind from the activity binding dialog. For this step, bind n1 to inputValue and (Return Value) to returnValue.

    Also, in the Properties pane, leave CanCreateInstance set to False to remain using that same workflow instance that was created in step 8. Otherwise, setting CanCreateInstance to True creates a new workflow instance for each operation invocation.

  22. Add ReceiveActivity and CodeActivity activities for each of the remaining EventDrivenActivity activities that are named for a math operation, starting with WaitToSubtract. For each ReceiveActivity specify the appropriate operation in the ServiceOperationInfo property and also remember to bind the operation parameters with the workflow member variables inputValue and returnValue.

    When you have finished, every math operation should have an associated ReceiveActivity and all CodeActivity activity event handlers should be implemented in the following manner:

        Private Sub codeActivity1_ExecuteCode(ByVal sender As System.Object, ByVal e As System.EventArgs)
            returnValue += inputValue
        End Sub
    
        Private Sub codeActivity2_ExecuteCode(ByVal sender As System.Object, ByVal e As System.EventArgs)
            returnValue -= inputValue
        End Sub
    
        Private Sub codeActivity3_ExecuteCode(ByVal sender As System.Object, ByVal e As System.EventArgs)
            returnValue *= inputValue
        End Sub
    
        Private Sub codeActivity4_ExecuteCode(ByVal sender As System.Object, ByVal e As System.EventArgs)
            returnValue /= inputValue
        End Sub
    
        private void codeActivity1_ExecuteCode(object sender, EventArgs e)
        {
            returnValue += inputValue;
        }
    
        private void codeActivity2_ExecuteCode(object sender, EventArgs e)
        {
            returnValue -= inputValue;
        }
    
        private void codeActivity3_ExecuteCode(object sender, EventArgs e)
        {
            returnValue *= inputValue;
        }
    
        private void codeActivity4_ExecuteCode(object sender, EventArgs e)
        {
            returnValue /= inputValue;
        }
    
  23. For the WaitToEndService EventDrivenActivity activity, drag and drop a ReceiveActivity activity inside WaitToEndService.

  24. In the Properties pane, under ServiceOperationInfo, click the ellipsis to open the Choose Operation dialog box.

  25. Select ShutdownService and click OK.

  26. In the OperationsState design view, drag and drop a SetStateActivity inside WaitToEndService below the ReceiveActivity activity.

  27. Select the SetStateActivity activity and in the Properties pane, under TargetStateName, select FinalState from the drop-down list.

To persist your workflow service

  1. Open the App.config file.

  2. Add a reference to SqlWorkflowPersistenceService in your behavior element as shown.

    <behavior name="WorkflowServiceTutorial.ServerWorkflowBehavior"  >
        <serviceMetadata httpGetEnabled="true" />
        <serviceDebug includeExceptionDetailInFaults="true" />
        <serviceCredentials>
        <windowsAuthentication
            allowAnonymousLogons="false"
            includeWindowsGroups="true" />
        </serviceCredentials>
              <workflowRuntime name="WorkflowServiceHostRuntime" validateOnCreate="true" enablePerformanceCounters="true">
                <services>
                  <add type="System.Workflow.Runtime.Hosting.SqlWorkflowPersistenceService, System.Workflow.Runtime, Version=3.0.00000.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
                       connectionString="Data Source=localhost\sqlexpress;Initial Catalog=NetFx35Samples_ServiceWorkflowStore;Integrated Security=True;Pooling=False"
                       LoadIntervalSeconds="1" UnLoadOnIdle= "true" />
                </services>
              </workflowRuntime>
    </behavior>
    

    The SqlWorkflowPersistenceService used in this tutorial is the same type of persistence service that can be used in workflow-only scenarios, which means that your workflow service state information will be persisted to a SQL database anytime the workflow instance is idle. This scenario is supported by default in .NET Framework version 3.5, but you can derive from WorkflowPersistenceService to persist data to other database stores.

    Also, because workflow service can use the persistence functionality of Windows Workflow Foundation, workflow service state information can be persisted during the execution of an operation's implementation, instead of after its completion like in a durable service.

    The connectionString attribute value in the PersistenceProviderElement is set to "WorkflowServiceStore." This is the name of the connection string that is used when trying to connect to your SQL database.

    Note

    This tutorial uses the NetFx35Samples_ServicesWorkflowStore database. To create the database, run the Createstores.cmd script from One-Time Setup Procedure for the Windows Communication Foundation Samples.

To build the solution

  1. Press F5 to build the solution and run it. WcfSvcHost.exe starts running and your service is hosted by it. WcfSvcHost.exe is a developer tool that hosts services for testing purposes. For testing purposes, the Sequential Workflow Service Library and State Machine Workflow Service Library templates automatically use the WcfSvcHost.exe application to host your workflow service so you do not have to create a host application yourself. For more information, see WCF Service Host (wcfSvcHost.exe) and WCF Test Client (wcfTestClient.exe). In the next task, Task 2: Create a Workflow Service Client, a client application is created that is used to invoke the service.

Comments

After you have finished creating the workflow service, Task 2: Create a Workflow Service Client describes how to create a workflow service client that can interact with this workflow service.

See Also

Concepts

How to: Configure a Workflow Service

Other Resources

Exercise 1: Create a Basic Workflow Service
Task 2: Create a Workflow Service Client

Copyright © 2007 by Microsoft Corporation. All rights reserved.
Last Published: 2010-03-04