Walkthrough: Implementing a Service by Using a Sequential Conversational Workflow
This walkthrough creates a conversational workflow operation. This operation models a simple order processing service. The first phase of the conversation receives order information and generates an OrderId. The second phase accepts the OrderId and returns an order placement confirmation message.
The walkthrough implements the conversational workflow in a BLSpecific service project named OrderProcessingBLSpecific in a DCS Solution project named OrderProcessing. The walkthrough also creates messages in a messages project named OrderProcessingMessages.
Before you begin
- Create a DCS solution in Visual Studio named OrderProcessing in the E:\Walkthroughs folder. For detailed instructions about creating a DCS solution, see Walkthrough: Creating a DCS Solution.
- Create a messages project in the DCS Solution project named OrderProcessingMessages. Create the project in the OrderProcessingNamespace.Messages namespace. For detailed instructions about how to create a messages project, see Walkthrough: Creating a DCS Messages Project.
Detailed Instructions
To create Request, Response, Error, and Exception Message classes in the OrderProcessingMessages project
In Solution Explorer, right-click OrderProcessingMessages, and then click Add Message Class.
In the Add Message Class dialog box, in the Class box, type PlaceOrderRequest, and then click Finish.
The following image shows the Add Message Class dialog box.
The AddMessageClass dialog box configured to create a new Message class named PlaceOrderRequest
Follow the same procedure to add another Message class named PlaceOrderResponse.
Follow the same procedure to add two more Message classes named ConfirmOrderRequest and ConfirmOrderResponse.
In Solution Explorer, right-click OrderProcessingMessages, and then click Add Error and Exception Classes.
In the Add Error and Exception Classes dialog box, in the Exception Class box type PlaceOrderException, in the Error Class box type PlaceOrderError, and then click Finish.
After you create the default Message classes, you can customize them to contain the required fields.
To customize the generated classes
In Solution Explorer, under OrderProcessingMessages, right-click PlaceOrderRequest.cs, and then click View Code.
In the PlaceOrderRequest.cs file, expand the Private Fields region, and then add a line of code to create private string fields named _CustomerName, _ProductName, and _ShippingAddress.
Your code should resemble the following example.
-
#region Private Fields private string _CustomerName; private string _ProductName; private string _ShippingAddress; #endregion
Expand the Public Properties region, and add code to create public properties to expose the _CustomerName, _ProductName, and _ShippingAddress fields. Name the properties CustomerName, ProductName, and ShippingAddress respectively, and decorate each property with the DataMember attribute. This enables the serialization runtime to serialize the Message class correctly.
Your code should resemble the following example.
-
#region Public Properties [DataMember] public string CustomerName { get { return _CustomerName; } set { _CustomerName = value; } } [DataMember] public string ProductName { get { return _ProductName; } set { _ProductName = value; } } [DataMember] public string ShippingAddress { get { return _ShippingAddress; } set { _ShippingAddress = value; } } #endregion
On the File menu, click SavePlaceOrderRequest.cs.
On the File menu, click Close.
In Solution Explorer, under OrderProcessingMessages, right-click PlaceOrderResponse.cs, and then click View Code.
In the PlaceOrderResponse.cs file, expand the Private Fields region, and then add a line of code to create a private integer field named _OrderId.
Your code should resemble the following example.
-
#region Private Fields private int _OrderId; #endregion
Expand the Public Properties region, and add code to create a public property to expose the private integer field. Name the property OrderId, and decorate it with the DataMember attribute.
Your code should resemble the following example.
-
#region Public Properties [DataMember] public int OrderId { get { return _OrderId; } set { _OrderId = value; } } #endregion
On the File menu, click SavePlaceOrderResponse.cs.
On the File menu, click Close.
Repeat steps 6 through 10 to add a property named OrderId to the ConfirmOrderRequest.cs Message class.
In Solution Explorer, under OrderProcessingMessages, right-click ConfirmOrderResponse.cs, and then click View Code.
In the PlaceOrderResponse.cs file, expand the Private Fields region, and then add a line of code to create a private bool field named _OrderPlaced.
Your code should resemble the following example.
-
#region Private Fields private bool _OrderPlaced; #endregion
Expand the Public Properties region, and add code to create a public property to expose the private field. Name the property OrderPlaced, and decorate it with the DataMember attribute.
Your code should resemble the following example.
-
#region Public Properties [DataMember] public bool OrderPlaced { get { return _OrderPlaced; } set { _OrderPlaced = value; } } #endregion
On the File menu, click SaveConfirmOrderResponse.cs.
On the File menu, click Close.
On the Build menu, click BuildOrderProcessingMessages, and then verify that there are no errors.
After you create the messages classes, you can create the BLSpecific project and implement the operation.
To create a BLSpecific project
In Solution Explorer, right-click the BLSpecific folder, point to Add, and then click BL Specific.
In the Add New Project dialog box, in the Templates list, click BL Specific.
In the Name box, type OrderProcessingBLSpecific and then click Browse.
In the ProjectLocation dialog box, browse to the E:\Walkthroughs\OrderProcessing\BLSpecific folder, and then click OK.
In the Add New Project dialog box, click OK.
The following figure shows the Add New Project dialog box.
The Add New Project dialog box, configured to create a new BL Specific project named OrderProcessingBLSpecfic in the E:\Walkthroughs\OrderProcessing\BLSpecific folder.
In the Create New BL Specific dialog box, in the Namespace box, type OrderProcessingNamespace
In the Service Name box, type OrderProcessingService, and then click Finish.
The following image shows the Create New BL Specific dialog box.
The Create New BL Specific dialog box configured to create a new BL Specific project in the OrderProcessingNamespace, and create a service instance named OrderProcessingService
Visual Studio generates the project by using the property values specified.
To create a conversational workflow operation
In Solution Explorer, right-click OrderProcessingBLSpecific, and then click Create New OperationRequest/Response.
In the Add New Operation Request/Response dialog box on the OperationConfiguration page, in the OperationName field, type PlaceOrder, and then click Next.
The following image shows the Operation Configuration page.
The Operation Configuration page of the Add New Operation Request/Response dialog box, configured to create a new operation named PlaceOrder.
On the Messages Selector page, click the ellipsis button (…) adjacent to the Select type of Request message box.
In the Please choose a file dialog box, browse to the E:\Walkthroughs\OrderProcessing\Messages\OrderProcessingMessages\bin\Debug folder, click OrderProcessingMessages.dll, and then click Open.
In the Add New Operation Request/Response dialog box on the Messages Selector page, configure the operation messages as follows, and then click Next:
-
Select type of Request message: PlaceOrderRequest
Select type of Response message: PlaceOrderResponse
Select type of Error: OrderProcessingError
Select type of Exception: OrderProcessingException
-
Note
When you first create the conversational workflow operation, specify the messages that make up the first phase of the conversation. You will add properties and functionality to the workflow itself to enable further conversation phases.
The following image shows the Messages Selector page.
The Messages Selector page of the Add New Operation Request/Response dialog box, configured to set the operation Request message to PlaceOrderRequest and the Response message to PlaceOrderResponse.
On the Messages Assemblies References page, in the AssembliesReferences list, make sure that the OrderProcessingMessages (Project) item is selected, and then click Finish.
The following image shows the Messages Assemblies References page.
The Messages Assemblies References page of the Add New Operation Request/Response dialog box
You now have added a request/response operation to the BLSpecific project, which at this point is still a standard specific workflow operation. You must add conversational workflow functionality to the workflow itself to produce a conversational workflow implementation.
To implement conversational workflow functionality
In Solution Explorer, in the OrderProcessingBLSpecific project, under PlaceOrder, right-click PlaceOrderWorkflow.cs, and then click View Code.
Expand the Properties accessor code region, and add code to the region to create local instances of the ConfirmOrderRequest and ConfirmOrderResponseMessage classes. You can follow the format used to define the existing Request and Response properties.
-
Note
Creating these properties in the code-behind file lets you configure the WaitForEvent and SendResponse activities to use the correct messages for each phase of the conversation.
Your code should resemble the following example.
-
#region Properties accessor... ... private OrderProcessingNamespace.Messages.ConfirmOrderRequest _ConfirmRequest; public OrderProcessingNamespace.Messages.ConfirmOrderRequest ConfirmRequest { get { return _ConfirmRequest; } set { _ConfirmRequest = value; } } private OrderProcessingNamespace.Messages.ConfirmOrderResponse _ConfirmResponse; public OrderProcessingNamespace.Messages.ConfirmOrderResponse ConfirmResponse { get { return _ConfirmResponse; } set { _ConfirmResponse = value; } } #endregion
In Solution Explorer, right-click PlaceOrderWorkflow.cs, and then click View Designer.
In the workflow designer, drag a Code activity from the toolbox onto the workflow service, and drop it at the top of the workflow sequence.
Change the (Name) property to placeOrder, and then double-click the activity to create an event handler in the code-behind file.
In the placeOrder_ExecuteCode method, add a line of code to set the Response.OrderId property to 1.
Your code should resemble the following example.
-
private void placeOrder_ExecuteCode(object sender, EventArgs e) { this.Response.OrderId = 1; }
-
Note
This code simulates sending the order data to the database and retrieving an automatically generated order number.
Switch to the workflow designer.
From the toolbox in the DCS group, drag a SendResponse activity onto the designer surface, and drop it below the placeOrder activity.
Change the activity (Name) property to sendPlaceOrderResponse.
Bind the activity Response property to the workflow Response property:
-
- Click the Response property, and then click the ellipsis button (…) that appears.
- In the Bind 'Response' to an activity's property dialog box, on the Bind to an existing member tab, click Response, and then click OK.
From the toolbox in the DCS group, drag a WaitForEvent activity onto the designer surface, and drop it below the sendPlaceOrderResponse activity.
Change the (Name) property to waitForConfirmOrderEvent, and the Action property to ConfirmOrder.
Change the InputType property to OrderProcessingNamespace.ConfirmOrderRequest.
-
Click the InputType property, and then click the ellipsis button (…) that appears.
In the Browse and Select a .NET Type dialog box, in the Type list, click OrderProcessingMessages.
Under Type Name, click ConfirmOrderRequest, and then click OK.
The following image shows the Browse and Select a .NET Type dialog.
The Browse and Select a .NET Type dialog box configured to select the ConfirmOrderRequest message from the OrderProcessingMessages assembly.
Bind the InputData property to the workflow ConfirmRequest property.
-
- Click the InputData property, and then double-click the Bind Property icon.
- In the Bind 'InputData' to an activity's property dialog box, on the Bind to an existing member tab, click ConfirmRequest, and then click OK.
Change the ResponseType property to OrderProcessingNamespace.ConfirmOrderResponse.
-
- Click the ResponseType property, and then click the ellipsis button (…) that appears.
- In the Browse and Select a .NET Type dialog box, in the Type list, click OrderProcessingMessages.
- Under Type Name, click ConfirmOrderResponse, and then click OK.
Change the WithResponse property to True.
From the toolbox, drag a Code activity onto the workflow service, and drop it below the waitForConfirmOrderEvent activity.
Change the (Name) property to confirmOrder, and then double-click the activity to create an event handler in the code-behind file.
In the confirmOrder_ExecuteCode method, add code to check whether the ConfirmRequest.OrderId value matches the Response.OrderId value. If the values match, set the ConfirmResponse.OrderPlaced value to true; otherwise, set it to false.
Your code should resemble the following example.
-
private void confirmOrder_ExecuteCode(object sender, EventArgs e) { ConfirmResponse = new OrderProcessingNamespace.Messages.ConfirmOrderResponse(); if (Response.OrderId == ConfirmRequest.OrderId) ConfirmResponse.OrderPlaced = true; else ConfirmResponse.OrderPlaced = false; }
-
Note
This code simulates confirming the order in the database. If the client application changes the OrderId value between calls to the service, the response is false; otherwise, the response is true.
Switch to the workflow designer.
From the toolbox in the DCS group, drag a SendResponse activity onto the designer surface, and drop it below the confirmOrder activity.
Change the (Name) property to sendConfirmOrderResponse, and set the RelatedActivity property to waitForConfirmOrderEvent.
Bind the Response property to the workflow ConfirmResponse property.
-
- Click the Response property, and then click the ellipsis button (…) that appears.
- In the Bind 'Response' to an activity's property dialog box, on the Bind to an existing member tab, click ConfirmResponse, and then click OK.
Your workflow should resemble the following image.
A conversational sequential workflow, containing two conversation phases. Each phase contains a single Code activity that performs the phase functionality.
Save the workflow file and build the project. Verify that there are no build errors.
You have now implemented the conversational workflow functionality. However, by default, the stub generated for this workflow only exposes the initial PlaceOrder operation in the conversation, and not the operation that enables the client application to invoke the ConfirmOrder operation. To expose the ConfirmOrder operation, you use the Update Stub and Operations recipe.
To generate Operation events for subsequent message calls
In Solution Explorer, right-click the OrderProcessingBLSpecific project, and then click UpdateStubandOperations.
In the Update Stub and Operations dialog box, in the Event list, click PlaceOrder.ConfirmOrder, and then click Apply.
The following image shows the Update Stub and Operations dialog box.
The Update Stub and Operations dialog box, configured to update the service stub with the PlaceOrderConfirmOrder operation.
-
Note
For each phase of each conversational workflow that you produce, you must select the event that triggers that phase from the event list, and then click Apply to enable Visual Studio to generate the required event settings.
In the Update Stub and Operations dialog box, click Next.
Rebuild the project and verify that there are no errors.
You have now implemented a conversational workflow operation and generated the required event code to enable a client application to invoke each stage in the conversation.
Note
When you build the client application for this service, you must use the same Context object each time that the client application calls the service to make sure that DCS correlates messages and operations correctly.
You can build services that use different mechanisms to correlate requests made by client applications to a specific service instance. For more information, see How DCS Implements Services and Operations.
You can now deploy the service and build the client application. For more information, see Walkthrough: Deploying DCS Services by Using Visual Studio. For more information about building client applications, see Building Client Applications.
See Also
Walkthrough: Creating a DCS Solution
Walkthrough: Creating a DCS Messages Project
How DCS Implements Services and Operations