Windows Workflow Foundation Feature Specifics
.NET Framework version 4 adds a number of features to Windows Workflow Foundation. This document describes a number of the new features, and gives details about scenarios in which they may be useful.
The messaging activities (Receive, SendReply, Send, ReceiveReply) are used to send and receive WCF messages from your workflow. Receive and SendReply activities are used to form a Windows Communication Foundation (WCF) service operation that is exposed via WSDL just like standard WCF web services. Send and ReceiveReply are used to consume a web service similar to a WCF ChannelFactory; an Add Service Reference experience also exists for Workflow Foundation that generates pre-configured activities.
Right-click on the project and select Add Service Reference. Point to an existing web service WSDL and click OK. Build your project to show the generated activities (implemented using Send and ReceiveReply) in your toolbox.
Samples for these activities can be found in the following sections:
A BestPriceFinder service calls out to multiple airline services to find the best ticket price for a particular route. Implementing this scenario would require you to use the message activities to receive the price request, retrieve the prices from the back-end services, and reply to the price request with the best price. It would also require you to use other out-of-box activities to create the business logic for calculating the best price.
The WorkflowServiceHost is the out-of-box workflow host that supports multiple instances, configuration, and WCF messaging (although the workflows aren’t required to use messaging in order to be hosted). It also integrates with persistence, tracking, and instance control through a set of service behaviors. Just like WCF’s ServiceHost, the WorkflowServiceHost can be self-hosted in a console/WinForms/WPF application or Windows service, or web-hosted (as a .xamlx file) in IIS or WAS.
In Visual Studio 2010, create a WCF Workflow Service Application project: this project will be set up to use WorkflowServiceHost in a web-host environment.
In order to host a non-messaging workflow, add a custom WorkflowHostingEndpoint that will create the instance based on a message.
Samples for the WorkflowServiceHost can be found in the following sections:
A BestPriceFinder service calls out to multiple airline services to find the best ticket price for a particular route. Implementing this scenario would require you to host the workflow in WorkflowServiceHost. It would also use the message activities to receive the price request, retrieve the prices from the back-end services, and reply to the price request with the best price.
A correlation is one of two things:
A way of grouping messages together; that is, the relationship between a request message and its reply.
A way of mapping a piece of data to a service instance
To get started with correlation, create a new project in Visual Studio. Create a variable of type CorrelationHandle.
An example of correlation used to group messages together is a Request-Reply correlation that groups messages together.
An example of mapping a piece of data to a service instance is content-based correlation which maps a piece of data (for example, an order ID) to a particular workflow instance.
On any messaging activity, click on the CorrelationInitializers property and add a QueryCorrelationInitializer using the CorrelationHandle variable created above. Double-click on the desired property on the message (e.g. OrderID) from the drop-down menu. Set the CorrelatesWith property to the CorrelationHandle variable used above.
An order-processing workflow is used to handle new order creation and updating existing orders that are in process. Implementing this scenario would require you to host the workflow in WorkflowServiceHost and use the messaging activities. It would also require correlation based on the orderId to ensure that updates are made to the correct workflow.
The WCF configuration schema is complex and provides users with many hard to find features. In .NET Framework 4.6.1, we have focused on helping WCF users configure their services with the following features:
Removing the need for explicit per-service configuration. If you do not configure any <service> elements for your service, and your service does not define programmatically any endpoint, then a set of endpoints will be automatically added to your service, one per service base address and per contract implemented by your service.
Enables the user to define default values for WCF bindings and behaviors, which will be applied to services with no explicit configuration.
Standard endpoints define reusable preconfigured endpoints, which have fixed values for one or more of the endpoint properties (address, binding and contract), and allow defining custom properties.
Finally, the ConfigurationChannelFactory<TChannel> allows you to do central management of WCF client configuration, useful in scenarios in which configuration is selected or changed after the application domain load time.
An experienced ASMX developer wants to start using WCF. However, WCF seems way too complicated! What is all that information that I need to write in a configuration file? In .NET 4, you can even decide to not have a configuration file at all.
An existing set of WCF services are very difficult to configure and maintain. The configuration file has thousands of lines of XML code that are extremely dangerous to touch. Help is needed to reduce that amount of code to something more manageable.
In .NET 3.5, there were a few limitations in the design of known types:
Adding known types dynamically, during serialization or deserialization, was not possible.
Serializers could not deal with unknown xsi:type information.
It was not possible for users to specify what xsi:type they would like to have appear on the wire to, for instance, make the size of a serialization instance on the wire smaller.
The DataContractResolver solves these issues in .NET 4.5.
Flowchart is a well-known paradigm to visually represent domain problems. It is a new control flow style we’re introducing in .NET 4. A core characteristic of Flowchart is that only one activity is executed at any given time. Flowcharts can express loops and alternative outcomes, but cannot natively express concurrent execution of multiple nodes.
In Visual Studio 2012, create a workflow console application. Add a Flowchart in the workflow designer.
The flowchart feature uses the following classes:
A flowchart activity can be used to implement a guessing game. The guessing game is very simple: the computer selects a random number and the player has to guess that number. When the player submits each guess, the computer shows him a hint (i.e. “try a lower number”). If the player finds the number in less than 7 attempts, he receives a special congratulation from the computer. This game can be implemented with a combination of the following procedural activities:
Procedural activities provide a mechanism to model sequential control flow using concepts that are familiar to programmers. These activities enable traditionally structured programming language constructs and, when appropriate, provide language parity with common procedural languages such as C#/VB.
ParallelParallel: An intranet document management system has a document approval workflow. Documents need to be approved by people in several departments before they can be published to the intranet. There isn’t an established order for the approvals; they can occur at any time while the document is in the “approval pending” phase. When a user submits a document for review it must be approved by her direct manager, the intranet administrator, and the internal communications manager.
ParallelForEach<T>: A WF application manages corporate buys within a large company. The corporate rules dictate that before planning any purchase operation, the valuations of three different vendors is required. An employee from the buying department selects three vendors from the company’s vendor list. After these vendors have been selected and notified, the company will wait for their economic proposals. The proposals can come in any order. To implement this scenario in WF, we use a ParallelForEach<T> that will iterate through our collection of vendors and ask for their economic proposals. After all offers are gathered, the best one is selected and displayed.
The InvokeMethod activity allows invoking public methods in objects or types in scope. It supports invoking instance and static methods with or without parameters (including parameter arrays), and generic methods. It also allows executing method synchronously and asynchronously.
A method in an object in scope needs to be invoked. For example, a value needs to be added to a dictionary. The Add method of the instance of the dictionary is invoked, and the key and value are provided.
A method needs to be invoked on a legacy CLR object. Instead of creating a custom activity to wrap the call to that legacy class, if it is in scope during the workflow execution, InvokeMethod can be used.
The TryCatch activity provides a mechanism for catching exceptions that occur during the execution of a set of contained activities (similar to the Try/Catch construct in C#/VB). TryCatch provides exception handling at the workflow level. When an unhandled exception is thrown, the workflow is aborted and the Finally block won’t be executed. This behavior is consistent with C#.
In Visual Studio 2012, create a workflow console application. Add a TryCatch activity in the workflow designer.
Designer Documentation: Error Handling Activity Designers
A set of activities needs to be executed, and specific logic needs to be executed when an error occurs. If during that error handling logic it is found that the error is not recoverable, the exception will be rethrown, and the parent activity (or the host) will deal with the problem.
The Pick Activity provides event-based control flow modeling in WF. Pick contains many branches where each branch waits for a particular event to occur before running. In this setup, a Pick behaves similar to a Switch<T> to which the Activity will execute only one of the set of events it is listening. Each branch is event driven and the event that occurs runs the corresponding branch first. All other branches cancel and stop listening for events.
A user needs to be prompted for input. Under normal circumstances, the developer would use a method call like ReadLine to prompt for a user’s input. The problem with this setup is that the program waits until the user enters something. In this scenario, a time-out is needed to unblock a blocking activity. A common scenario is one that requires a task to be completed within a given time duration. Timing out a blocking activity is a scenario where Pick adds a lot of value.
The Routing Service is designed to be a generic software Router that allows you to control how WCFmessages flow in between your clients and services. The Routing Service allows you to decouple your clients from your services, which gives you much more freedom in terms of the configurations that you can support and the flexibility you have when considering how to host your services. In .NET 3.5, clients and services were tightly coupled; a client had to know about all of the services it needed to talk to and where they were located. In addition, WCF in .Net Framework 3.5 had the following limitations:
Error handling was complex, as this logic had to be hard-coded into the client.
Clients and services had to always use the same bindings.
Services were rarely well factored: it is easier to have the client talk to one service which implements everything, rather than needing to choose between multiple services.
The routing service in .Net 4 is designed to make these problems easier to solve. The new routing service has the following features:
Content based routing (MessageFilter objects examine a message to determine where it should be sent.)
Protocol bridging (transport & message)
Error handling (the router catches communication exceptions and fails over to backup endpoints)
Dynamic (in memory) update of MessageFilterTable<TFilterData> and Routing Configuration.
The routing service is useful in the following scenarios:
Clients can talk to multiple services without having to address them all directly.
Clients can perform additional logic on a client request to determine where to route it
Decompose the operations a client performs into multiple service implementations without refactoring the client.
Clients and services can speak different bindings with different security settings.
Clients can be enabled to be more robust against failure or the unavailability of services.
WCF Discovery is a framework technology that allows you to incorporate a discovery mechanism to your application infrastructure. You can use this to make your service discoverable, and configure your clients to search for services. Clients no longer need to be hard coded with endpoint, making your application more robust and fault tolerant. Discovery is the perfect platform to build auto-configuration capabilities into your application.
The product is built on top of the WS-Discovery standard. It’s designed to be interoperable, extensible, and generic. The product supports two modes of operation:
Managed: where there is an entity on the network knowledgeable about existing services, clients query it directly for information. This is analogous to Active Directory.
Ad-hoc: where clients use multicast messages to locate services.
Furthermore, discovery messages are network protocol agnostic; you can use them on top any protocol that supports the mode requirements. For example, discovery multicast messages can be sent over the UDP channel or any other network that supports multicast messaging. These design points, combined with feature flexibility, allow you to adapt the discovery specifically to your solution.
A developer doesn't want to hard code endpoints, since it is unknown when my service will be available. Instead, the developer wants to choose a service at runtime. More decoupling, robustness, and auto-configuration is needed between the components in the application.
Workflow tracking provides insight into the execution of a workflow instance. The tracking events are emitted from a workflow at the workflow instance level and when activities within the workflow execute. A workflow tracking participant needs to be added to the workflow host to subscribe to tracking records. The tracking records are filtered using a tracking profile. The .Net Framework provides an ETW (Event Tracing for Windows) tracking participant, and a basic profile is installed in the machine.config file.
Open the web.config and add an ETW tracking behavior with no profile.
The default profile is used.
Open event viewer and enable the analytic channel in the following node: Event Viewer, Applications and Services Logs, Microsoft, Windows, Application Server-Applications. Right-click Analytic and select Enable Log.
Run the workflow service.
Observe the workflow tracking events in event viewer.
Conceptual documentation: Workflow Tracking and Tracing
The SqlWorkflowInstanceStore is a SQL Server-based implementation of an instance store. An instance store stores the state of a running instance together with all data necessary to load and resume that instance. The service host instructs the instance store to save the instance state if the workflow persists, and it instructs the instance store to load the instance state when a message arrives for that instance or a delay activity expires.
In Visual Studio 2012, create a Workflow that contains an implicit or explicit Persist activity. Add the SqlWorkflowInstanceStore behavior to your workflow service host. This can be done in code or in the application configuration file.
Conceptual documentation: SQL Workflow Instance Store.