Discussing how Microsoft Dynamics Improves an Organization's Operations.

Microsoft Dynamics

Subscribe to Microsoft Dynamics : eMailAlertsEmail Alerts newslettersWeekly Newsletters
Get Microsoft Dynamics : homepageHomepage mobileMobile rssRSS facebookFacebook twitterTwitter linkedinLinkedIn


Microsoft Dynamics Authors: Yeshim Deniz, Tim Park, Karen Miranda, Derek Harris, Dana Gardner

Related Topics: Software Testing Journal, Microsoft Dynamics , Science and Technology Innovation Journal

Blog Feed Post

Creating Correlated Workflow Services in WF4 / .NET4 : Part 1

In the past, Windows Workflow Foundation hasn't gotten a (deservedly so) bad reputation for being full of needless bloat

In the past, Windows Workflow Foundation hasn't gotten a (deservedly so) bad reputation for being full of needless bloat, overly complicated, and missing a lot of key things that make workflow productive for developers. As a result of that, Microsoft completely overhauled WF in the .NET Framework 4.0. One of the new features of WF4 is the concept of a workflow service. A workflow service is really nothing more than a workflow that is hosting WCF endpoints within the activity. This allows the workflow to progress from start to finish by communicating with external clients, such as websites, WPF applications, or Silverlight applications.

In the sample I'm going to illustrate in this series of blog posts, I'm going to create a customer service helpdesk application. There will be a single workflow at the core of the application - the customer issue workflow. A customer calls complaining that their widget is completely, horribly broken and the customer service rep starts a new issue. The issue then persists forever while communciation goes back and forth between the customer until finally one of the communication types is a "close ticket" type. This is a really simple workflow, but should be similar enough to things that people do in the "real world" that the sample won't feel contrived or too "hello world"-ish.

Some of the stuff that I'll be showing here will look very similar to the WCF/WF 4 Training Kit. The main issue I have with that training kit is that there's too much "magic" in it. By "magic" I mean stuff that was pre-created for you (like service references consuming the workflow services), so in this sample I'll walk you through how to create all that magic.

So to get started let's create a Sequential workflow and host it in a console app. I would normally host it inside IIS but I couldn't figure out how to get the HTTP metadata exchange stuff to be published on the .xamlx endpoint. To do this, open up Visual Studio 2010 Beta 1 and create a new project of type Sequential Workflow Console Application. Delete the Sequence1.xaml file and add a new sequential workflow to the project called SupportCall.xaml. From the toolbar, drag over a ReceiveAndSendReply activity from the Messaging category. This is the activity that is going to allow your workflow to receive a message via WCF and then do something with it.

Before we can do something with the message, we need to know what the message looks like. To do that, I added a class library to the solution and created a data contract class that looks like this:

[DataContract]
public class Customer
{
[
DataMember]
public string FirstName { get; set; }
[
DataMember]
public string LastName { get; set; }
[
DataMember]
public string CustomerID { get; set; }
[
DataMember]
public string Address1 { get; set; }
[
DataMember]
public string Address2 { get; set; }
[
DataMember]
public string City { get; set; }
[DataMember]
public string State { get; set; }
[
DataMember]
public string Zip { get; set; }
}

Add a reference to the contracts assembly from your workflow project and build the solution. Now you can modify the messaging piece of your workflow to accept messages of type Customer. To do this, you need to add a variable to the workflow.

Click the "Variables" button on the bottom left of the workflow designer surface and add a new variable named CurrentCustomer. When you choose the data type, click "Browse" and then type "Customer", you should find under the "Referenced Assemblies" tree node the customer class from the contracts assembly. When you've created this variable, your variables area should look something like this:

In order to receive data from a message, you need somewhere to put that data. In a workflow service, that somewhere is a variable. Now you can go and click on the Receive-Reply sequence and edit it so that the operation name is StartIssue, the service contract name is CustomerIssueService and the Value property (where the message value is stored) is the name of the variable we just created: CurrentCustomer. When you're done editing the receive-sendreply sequence, it should look something like this:

I modified the sendreply portion of the sequence and set the value to the following:

"A new issue has been created for " + CurrentCustomer.FirstName + " " + CurrentCustomer.LastName

If you're curious, the syntax for rules and expressions inside WF4 is ... *drumroll* ... Visual Basic!! This is important to keep in mind if you're in there editing rules and the rest of your application is written in C# - your stuff won't work if you start throwing C# syntax into the expression editors.

We're almost there. At this point we now have a workflow, but our solution won't compile because our Program.cs file from the stock VS template is full of junk related to launching Sequence1.xaml. Modify your Program.cs file to look like this:

namespace CustomerSupport.Services
{
using System;
using System.Linq;
using System.Threading;
using System.Activities;
using System.Activities.Statements;
using System.ServiceModel.Activities;
using System.ServiceModel.Description;
class Program
{
static void Main(string[] args)
{
string baseAddress = http://localhost:8081/SupportCall;


using (WorkflowServiceHost host =
new WorkflowServiceHost(typeof(SupportCall), new Uri(baseAddress)))
{
host.Description.Behaviors.Add(new ServiceMetadataBehavior() { HttpGetEnabled = true });
host.AddDefaultEndpoints();


host.Open();
Console.WriteLine("Customer Support Service listening at: " +
baseAddress);
Console.WriteLine("Press ENTER to exit");
Console.ReadLine();
host.Close();
}
}
}
}

Now we should be able to compile and when we run our console application (requires VS to be elevated!) we should see the message indicating that customer support service is running. We can quit the app now.

To create the client (we'll be making a better client in future blog posts) let's just create a new console application and add a reference to the contracts assembly. In order to add a service reference to the workflow service, you have to launch the workflow service console app from the command prompt because you can't add service references while Visual Studio is currently debugging something.

Modify the Program.cs for the client console application (after adding a service reference) to look like this:

static void Main(string[] args)
{
CustomerIssueService.CustomerIssueServiceClient svc =
new CustomerSupport.Client.CustomerIssueService.CustomerIssueServiceClient();
    Customer cust = new Customer();
cust.FirstName = "Bob";
cust.LastName = "Asdf";
cust.Address1 = "666 Evil Lane";
cust.Address2 = "";
cust.City = "Hades";
cust.State = "NJ";
cust.Zip = "99999";
cust.CustomerID = "ASDF";
string response = svc.StartIssue(cust);
Console.WriteLine(response);
Console.ReadLine();
}

Now you can run the application and you'll see a line of text indicating that a new issue has been created for customer Bob Asdf. In the next blog post, I'm going to walk through adding more steps to the workflow to make it more realistic, including adding another web service call in the same service that uses correlation so that we can progress multiple instances of multiple workflows and correlate the messages to the right workflows based on message content.

Some things to keep in mind as you wait eagerly for the next blog post are how the naming of the service contract and operation name affect the names of the methods and proxies created when you add a service reference to the workflow service.

Read the original blog entry...

More Stories By Kevin Hoffman

Kevin Hoffman, editor-in-chief of SYS-CON's iPhone Developer's Journal, has been programming since he was 10 and has written everything from DOS shareware to n-tier, enterprise web applications in VB, C++, Delphi, and C. Hoffman is coauthor of Professional .NET Framework (Wrox Press) and co-author with Robert Foster of Microsoft SharePoint 2007 Development Unleashed. He authors The .NET Addict's Blog at .NET Developer's Journal.