lmost any application requires some sort of workflow, where the application performs one or more actions through processes made up of multiple activities. Windows Workflow Foundation (WF) lets developers create these workflows using a rich set of activities that are very easy to use. Within the WF activities that make up a workflow, you may sometimes need to invoke an external WCF service, sending and receiving appropriate messages.
.NET 3.5 supported WF-to-WCF service interaction by supplying specific WF activities that could call an external WCF service from within a workflow. The drawback with this approach is that developers needed to use two different programming models to work with WCF and WF. For example, you had to define WCF artifacts and manage them separately—then integrate them with WF activities. However with .NET 4.0, you can define a WF workflow as a WCF service declaratively, with XAML (eXtensible Application Markup Language). This article introduces this new feature and showcases how you can leverage it to create declarative WCF services through workflows.
One key feature of .NET 4.0 is the seamless integration between WCF and WF. This integration greatly simplifies the developer experience around declarative workflows and services, and it's all made possible by the XAML-only model, which is completely based on declarative attributes. You can describe the workflow-based WCF service solely in XAML, including service contract definitions, endpoint configurations, and even the actual service implementation.
These declarative XAML-based services provide a layer of abstraction. Essentially, you create a model of the service by defining what you want the service to do, rather than writing code to specify how to do it.
Defining Service Contracts Declaratively
In earlier versions of the .NET Framework, a simple WCF service contract definition looked similar to the one shown below:
public interface IHelloWorld
string HelloWorld(string input);
Using the declarative WCF services feature in .NET 4.0, you could define the same service contract as follows:
<OperationArgument Name="input" Type="p:String" />
<OperationArgument Direction="Out" Name="result1"
The <ServiceContract> element specifies the name of the contract and serves as a container for the operation contracts that make up the service contract. As the name suggests, the <OperationContract> element specifies the operations exposed by the service. The parameters to an operation are represented by the <OperationArgument> elements, which are children of the <OperationContract> element. There will be one <OperationArgument> element for each argument or return value that the operation accepts or returns. The <OperationArgument> element holds information about the argument, such as its data type and direction. The Direction attribute specifies whether an argument is an In, Out, or In/Out argument.
After defining the service contract in XAML, the next step is to define how to project the contract onto the wire so that service consumers can leverage appropriate protocols to consume the service. .NET Framework 4.0 introduces a new feature named Contract Projection that lets you clearly separate the logical contract definition from the actual representation of the messages that are sent and received:
<OperationContract Name="HelloWorld" x:Name="HelloWorld">
<OperationArgument Name="Op1" Type="p:String" />
<OperationArgument Direction="Out" Name="Result"
By inheriting from the single logical service contract, you have an option to project different service contracts, such as SOAP- or REST-based contract projections, etc., based on the service consumers' needs.