Workflow and Windows Communication Foundation


Although you can accomplish a lot by pairing ASP.NET web services and Windows Workflow Foundation, a whole new world of connected systems is being opened up with the release of Windows Communication Foundation (WCF). The following sections cover WCF at a high level and explain how you can use this new technology to enhance the Windows Workflow Foundation functionality to interact with connected systems.

An Introduction to WCF

Simply put, Windows Communication Foundation is the next-generation platform from Microsoft for developing and running connected systems. This technology is also meant to encapsulate other distributed-systems technologies that Microsoft introduced in the past. Technologies such as Microsoft Message Queuing (MSMQ), .NET Remoting, and ASP.NET Web Services (ASMX) all work great with the WCF platform. WCF is meant to be the overriding piece of technology that brings all these legacy technologies together. Furthermore, WCF tries to abstract technology from the implementation of business logic. This means that decisions about which transport your application should use can be delayed until later in the development cycle. Previously, decisions about whether to use .NET Remoting or ASMX would have to be made up front.

A common way to explain the basics of WCF is to discuss the ABCs:

  • Addresses

  • Binding

  • Contracts

Every WCF service has endpoints, which all have addresses, bindings, and contracts. An endpoint’s address describes its public location, such as an HTTP URL. The binding describes an endpoint’s transport technology, such as HTTP or TCP. A contract describes an endpoint’s abilities. For example, an endpoint’s contract might dictate that it is able to look up a customer’s orders using a unique customer identifier.

As previously mentioned, a service’s attributes can be configured after development so that an endpoint’s binding can be changed from HTTP to MSMQ at the drop of a hat. The same goes for an endpoint’s address. The contact, however, needs to be defined up front. This is rather obvious because you must know what a service is able to do before you build it.

WCF service contracts are defined in a manner quite similar to that of Windows Workflow Foundation data exchange contracts. Standard .NET interfaces, along with WCF-specific attributes, are used to identify a service’s behavior. The following is a quick example of a contract for a service that handles a software system’s user management capabilities:

  using System.ServiceModel; [ServiceContract] public interface IUserManagement {     [OperationContract]     int CreateUser(string username);     [OperationContract]     User GetUserInfo(int userID);     [OperationContract]     void DeleteUser(int userID); } 

A few things can be determined by studying this code. First, the vital classes relevant to WCF are found in the System.ServiceModel namespace. Second, an interface is designated as a service contact by being decorated with the ServiceContract attribute. Finally, every method that should be available publicly on the service should be decorated with the OperationContract attribute. Other methods that should not be available publicly on the service can be included in the interface - they would just not be decorated with the OperationContract attribute.

One of the nice things about WCF is that you can configure almost everything about a service and its respective endpoints. This means that you can change a service’s address, binding, and contract by modifying a configuration file. Obviously, this is much more flexible than forcing this information into compiled code.

The following code is an example of an App.config or Web.config file that is hosting a service with a single endpoint:

  <?xml version="1.0" encoding="utf-8" ?> <configuration>    <system.serviceModel>       <services>          <service             name="YourNamespace.YourServiceClass"             behaviorConfiguration="CustomBehaviorName">             <endpoint                address="http://localhost:8080/myService"                binding="wsHttpBinding"                contract="YourNamespace.IYourServiceContractInterface" />          </service>       </services>       <behaviors>          <serviceBehaviors>             <behavior name="CustomBehaviorName">                <serviceMetadata                   httpGetUrl="http://localhost:8080/myService/metadata"                   httpGetEnabled="true" />             </behavior>          </serviceBehaviors>       </behaviors>    </system.serviceModel> </configuration> 

There are a few things to look for when studying this markup. First, start by looking at the endpoint node. The ABCs are represented in here. The endpoint’s address can be found at http://localhost:8080/myservice; its binding is using the out-of-the-box wsHttpBinding binding; and the contract points to an interface that presumably was written by the developer of the service.

wsHttpBinding is one of many preconfigured bindings that ship with WCF. These preconfigured bindings have settings that would commonly be needed by developers and are available for ease of use. For example, the wsHttpBinding dictates that the messages sent to and from the associated endpoint conform to such standards as WS-Security 1.1 and SOAP 1.2.

Next, notice that the endpoint node lives inside a service node that lives inside the services node. The services node is simply a container for one or more service nodes, which contain one or more endpoint nodes. The service node in this example points to a specific class that will act as the host of the service. It also has a behaviorConfiguration attribute that points to a behavior node a little lower in the configuration file.

The behavior node can define many fine-grained details related to a service, but in this example, it simply dictates that the service’s metadata (or WSDL) will be available for consumption at http://localhost:8080/myService/metadata. The Web Service Definition Language (WSDL) informs interested parties (such as client applications) what the web service does and what kind of information it expects and returns.

Because WCF is such a flexible and feature-rich platform, there is a lot more to it than can be explained in this book. If you need to develop a connected system with workflow, you should research WCF. Sites such as http://msdn.microsoft.com have tons of resources related to API references as well as technical articles.

Using WCF to Expose a Workflow as a Windows Service

This book has already shown you several ways to host the workflow runtime. Chapter 13 discusses some of the pitfalls associated with hosting in a web environment. Hosting the runtime in a volatile application such a Windows Forms application might have its dangers as well because it is not always guaranteed to be running. An alternative that enables you to have full control over threading considerations and when the application is available is hosting the workflow runtime in a Windows service, sometimes called an NT service.

When hosting the workflow runtime in a Windows service, you have to expose the functionality to the outside world. In the past, this was accomplished with technologies such as .NET Remoting. However, with the great functionality and flexibility provided by WCF, a new option is available.

In the following example, a workflow is responsible for adding potential new employees to the system and then converting the potential hires to full-time employees based on an approval status. The software should be able to process information about a candidate and send out a request for approval. Then a hiring manager enters his or her approval status, which dumps the candidate from the system if unapproved or converts him or her to a hired employee if approved.

Remember, this system will be exposed through a Windows service under the guise of a web service. However, to the calling software, this employee service will look no different from a standard XML web service. This is the functionality provided by WCF. Behind the scenes, however, the hosting of the workflow runtime is much different from hosting in a standard ASMX web service.

Before getting to the particulars of the Windows Service and WCF implementation, take a look at some of the workflow-specific code. Figure 14-6 shows the workflow implementation. It consists of a CallExternalMethod activity that sends out a request for employee approval and then a Listen activity that waits for an approval or rejection event to be raised from the host.

image from book
Figure 14-6

The following code shows a standard workflow communication contract decorated with the ExternalDataExchangeAttribute. It includes a method that allows the workflow’s host to send an external request for the employee service as well as two events that represent either an approval or a rejection coming in from the outside world.

  [ExternalDataExchange] public interface IEmployeeService {     void RequestApproval();     event EventHandler<ExternalDataEventArgs> Approved;     event EventHandler<ExternalDataEventArgs> Rejected; } 

The following code is the implementation of the preceding communication contract:

  public class EmployeeService : IEmployeeService {     public event EventHandler<ExternalDataEventArgs> Approved;     public event EventHandler<ExternalDataEventArgs> Rejected;     public void RequestApproval()     {         // do something to request approval...         // perhaps send an email to someone     }     public void ApproveEmployee(Guid instanceId)     {         if (this.Approved != null)         {             this.Approved(null, new ExternalDataEventArgs(instanceId));         }     }     public void RejectEmployee(Guid instanceId)     {         if (this.Rejected != null)         {             this.Rejected(null, new ExternalDataEventArgs(instanceId));         }     } } 

Two public methods, ApproveEmployee and RejectEmployee, are added to raise the Approved and Rejected events, respectively, when called. Also, the RequestApproval method is implemented in order to perform whatever actions are necessary to request an approval for the employee.

Now that the workflow code has been covered, it’s time to move on to the WCF and Windows service code. The following block of code shows a communication contract, but this one is for WCF. Like Windows Workflow Foundation, WCF uses .NET interfaces to define the public communication interfaces between services and the outside world. Also like Windows Workflow Foundation, .NET attributes are used to designate the interfaces as important to WCF.

   [ServiceContract(Namespace = "http://Kitta.Workflow")] public interface IServiceContract {     [OperationContract]     void CreateEmployee(string name);     [OperationContract]     void ApproveEmployee(Guid instanceId);     [OperationContract]     void RejectEmployee(Guid instanceId); } 

This IServiceContract interface is decorated with the ServiceContract attribute, which can be found in the System.ServiceModel. If you have the .NET Framework 3.0 installed, the WCF classes are available to you just as the Windows Workflow Foundation classes are.

The ServiceContract attribute tells the WCF runtime that the designated interface is meant to be just that - a service contract. This attribute also allows you to define a unique namespace for the WCF service. The methods are in turn decorated with an attribute called OperationContract. This attribute lets the WCF runtime know that the methods should be exposed as public methods on the service.

The next piece of code is the implementation of the Windows service itself, WorkflowHostService:

  public partial class WorkflowHostService     : ServiceBase, IServiceContract {     private WorkflowRuntime workflowRuntime;     private EmployeeService employeeService;     private ServiceHost serviceHost;     public WorkflowHostService()     {         InitializeComponent();         this.workflowRuntime = new WorkflowRuntime();         ExternalDataExchangeService dataExchangeService =             new ExternalDataExchangeService();         this.workflowRuntime.AddService(dataExchangeService);         this.employeeService = new EmployeeService();         dataExchangeService.AddService(this.employeeService);     }     protected override void OnStart(string[] args)     {         workflowRuntime.StartRuntime();         Uri baseAddress =             new Uri("http://localhost:8080/createEmployeeService");         serviceHost =             new ServiceHost(typeof(WorkflowHostService), baseAddress);         // open the host         // this is what starts the Windows Service listening for requests         serviceHost.Open();     }     protected override void OnStop()     {         workflowRuntime.StopRuntime();         serviceHost.Close();     }     public void CreateEmployee(string name)     {         Dictionary<string, object> parms = new Dictionary<string, object>();         parms.Add("EmployeeName", name);         WorkflowInstance instance =             this.workflowRuntime.CreateWorkflow(typeof(EmployeeService), parms);         instance.Start();     }     public void ApproveEmployee(Guid instanceId)     {         this.employeeService.ApproveEmployee(instanceId);     }     public void RejectEmployee(Guid instanceId)     {         this.employeeService.RejectEmployee(instanceId);     } } 

To be a Windows service, a class must inherit from the ServiceBase class, which is found in the System.ServiceProcess namespace. Also, notice that the WorkflowHostService class implements the IServiceContact interface, which was defined earlier. Therefore, the code that is called by external consumers of the WCF service are implemented in this class.

There are a few points of interest in this class. First, take a look at the constructor. Here, usual code can be found to ready the workflow runtime as well as the ExternalDataExchangeService. The custom EmployeeService class is also added to the data exchange service.

The OnStart method is overridden from the ServiceBase class and is called when the Windows service is started. It is here that the workflow runtime is started and the WCF service is configured and started. The code found in this method is all that is needed to run in order to start allowing incoming calls on the service. The OnStop method conversely stops the workflow runtime and the WCF service.

The remainder of the methods - CreateEmployee, ApproveEmployee, and RejectEmployee - are all implemented per the service contract interface. The ApproveEmployee and RejectEmployee methods simply call methods of the same name on the EmployeeService, which is the data exchange service between the host and the workflow.

The CreateEmployee method off a new workflow instance based on the information passed in from the external service caller. The code in this method should look pretty familiar to you by now.

Although the code looks pretty straightforward, there is a lot going on behind the scenes to allow all this goodness to happen. The WCF code in the OnStart method would not work without the settings in the App.config file. Take a look at its contents in the following code:

  <?xml version="1.0" encoding="utf-8" ?> <configuration>   <system.serviceModel>     <services>       <service name="Kitta.WorkflowService.WorkflowHostService"                behaviorConfiguration="EmployeeServiceBehavior">         <endpoint address="http://localhost:8080/createEmployeeService"                   binding="wsHttpBinding"                   contract="Kitta.WorkflowService.IServiceContract" />       </service>     </services>     <behaviors>       <serviceBehaviors>         <behavior name="EmployeeServiceBehavior">           <serviceMetadata               httpGetUrl="http://localhost:8080/workflow/metadata"               httpGetEnabled="true" />         </behavior>       </serviceBehaviors>     </behaviors>   </system.serviceModel> </configuration> 

Almost everything contained in the App.config file is specific to WCF. The system.serviceModel node encompasses all the WCF-specific settings. The services node contains a definition for the service used in this example and points to the service class Kitta.WorkflowService.WorkflowHostService. Within the service node is an endpoint node. Remember, endpoints are the public interface that the outside world uses to access a WCF service. In this example, the endpoint node specifies that the service should have an HTTP interface, making it a standard web service. In addition, the endpoint’s interface is defined with the IServiceContract interface, which was covered earlier.

The other interesting piece of the configuration file is in the behaviors node. It is here that the behavior for the employee WCF service is defined. In this example, the behavior encompasses allowing web service metadata, or WSDL, to be exposed through the defined URL. By exposing WSDL publicly, utilities such as the Add Web Reference wizard in Visual Studio and the wsdl.exe command-line utility are able to generate proxy classes to abstract the calling of a web service using a .NET class.



Professional Windows Workflow Foundation
Professional Windows Workflow Foundation
ISBN: 0470053860
EAN: 2147483647
Year: 2004
Pages: 118
Authors: Todd Kitta

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net