Workflows Published via ExternalDataExchange Services
You have the option of
building the workflow independently of any communication framework and
creating a hosting environment that handles all inbound and outbound
communication for you. This approach provides the greatest amount of
flexibility with regard to
message formatting, communication protocol support, message
correlation, and the processing of overlapping request-response
operations. However, that flexibility comes at the expense of having to
build the communication layer yourself.
First, you need to implement all communications of the workflow with HandleExternalEvent and CallExternalMethod operations instead of using the communication activities WebServiceInput, WebServiceOutput and WebServiceInvoke. This approach does not work with WF 4.0 because HandleExternalEvent and CallExternalMethod
were removed from the framework. A similar solution can be developed
with WF 4.0 bookmarks, but having to program complete custom hosting
extensions should be considered a last resort.
You can also choose to build
custom activities that work with services provided by your custom
hosting environment for sending and receiving messages. The HandleExternalEvent and CallExternalMethod
activities can interact with the custom hosting environment through a
communication service. The communication service can post events from
the workflow container to the workflow runtime engine and handle method
invocations from the workflow. This is an in-process service attached to
the WorkflowHost to optimize performance and avoid passing security contexts between processes. You can add these services to the WorkflowHost object that manages all the workflows.
The upcoming example adds two services to the runtime:
ExternalDataExchangeService (required for communication between the workflow and its host via HandleExternalEventActivity and CallExternalMethodActivity)
taskService (a custom service that works together with ExternalDataExchnageService to handle method invocations from within workflows)
Example 11.
using (WorkflowRuntime workflowRuntime = new WorkflowRuntime()) { ExternalDataExchangeService dataExchangeService = new ExternalDataExchangeService(); workflowRuntime.AddService(dataExchangeService); dataExchangeService.AddService(taskService); workflowRuntime.StartRuntime(); }
|
The workflow runtime
automatically calls these services when necessary and the workflow
runtime calls the Data Exchange service when it needs to communicate
with the workflow host (Figure 14).
The workflow container
passes messages to the workflow by raising an event for the workflow to
handle. The contract interface defines the event signature. Behind the
scenes, ExternalDataExchangeService creates an appropriate event handler and attaches it to the custom event service.
This next example shows that passing data to a workflow is no different than raising any other event in a .NET program:
Example 12.
dataExSvc.RaiseApproveOrderEvent(wfId, quoteData); class OrderDataExchangeService : IOrderContract { public event EventHandler<ApproveOrderEventArgs> ApproveOrderEvent; public void RaiseApproveOrderEvent(Guid wfId, ApproveRequest order, ApproveResponse resp, ManualResetEvent waiter) { if(ApproveOrderEvent != null) { ApproveOrderEvent(null, new ApproveOrderEventArgs(wfId, order)); } } ... }
|
The IOrderContract interface implemented by this data exchange service defines the contract for the workflow:
Example 13. The code highlighted with red represents incoming messages
posted to the workflow, whereas the bold code represents outgoing
messages originating from the workflow. Note that all incoming
interfaces are defined as events with all event argument classes
deriving from ExternalDataEventArgs. All outgoing interfaces are just straight-forward method definitions.
[System.Workflow.Activities.ExternalDataExchange] public interface IOrderContract { event EventHandler<CreateQuoteEventArgs> CreateQuoteEvent; event EventHandler<ApproveOrderEventArgs> ApproveOrderEvent; event EventHandler<RejectOrderEventArgs> RejectOrderEvent; void QuoteCreated(QuoteResponse response, ManualResetEvent completionEvent); void OrderApproved(ApproveResponse response, ManualResetEvent completionEvent); void OrderRejected(RejectResponse response, ManualResetEvent completionEvent); }
|
Since you control how the
workflow is published, support for formal contracts depends on how you
choose to implement the communication layer.
Note
When taking into account the Service Discoverability principle and the Metadata Centralization pattern, it is worth noting that because service interfaces for
workflows are based on either ASMX or WCF technology, WF orchestrations
expose the discovery interfaces provided by these technologies. For
example, retrieving the WSDL documents via a URL ending in ?wsdl.
WCF-based services also support
retrieving service metadata, such as WSDL definitions and policy
documents, via WS-MetadataExchange. However, you do have to explicitly
enable metadata retrieval in WCF.
Visual Studio can present WF
orchestrations and services packaged as custom activities in the
Toolbox pane to increase developer awareness of the common services
approved for broad consumption.
Note also that WF, in combination with WCF 4.0, allows for registration via the WS-Discovery industry standard.
WS-I BasicProfile Support
Publishing workflows as ASMX services enables the use of basic Web services through the WebServiceInput, WebServiceOutput, and InvokeWebService
activities. The former two handle requests and responses for a workflow
published as an orchestrated task service and the latter allows
workflows to interact with Web services. This feature is available in
all WF versions, but its limited support for contemporary WS standards
makes WCF a commonly preferred option.
Note that when you develop
ASMX services without WF, ASMX can emit errors for a non WS-I compliant
service interface. With WF services published through WF’s “Publish as
Web service” feature, you may not see these compliance warnings from the
compiler when you publish because the WebService
class is compiled behind the scenes. You need to separately check your
message type definitions for compliant namespace definitions and other
incompatibilities caught by the compiler.
Note
If you follow a
contract-first design approach, you can pay special attention to
designing your service contract for WS-I BasicProfile compliance. Tools
such as WSCF, WSCF.blue for WCF or the Web service Software Factory can
be used to help verify WS-I BasicProfile compliance as part of a
contract-first design process.
In
WF 3.5 and WF 4.0, WCF support for industry standard transports,
protocols and policies transfers to WF Workflow Services. All
communication aspects for Web services published into IIS can be
configured in the Web.Config file. The basicHttpBinding
configures a message exchange over SOAP and HTTP. This follows the
rules of the WS-I BasicProfile, in both service and consumer endpoint
configurations.
Exposing a WCF3.5 Workflow
Service in WAS or IIS required a .svc to bind the workflow to an
endpoint. The .svc file either referenced a CodeBehind service
definition or a workflow in a compiled assembly.
Here is a .svc file example for a compiled workflow:
Example 14.
<%@ ServiceHost Factory="System.ServiceModel.Activation. WorkflowServiceHostFactory" Service= "StandardMold.QuoteProcess.CustomerService" %>
|
The WorkflowServiceHostFactory loads the configuration matching the service type from the system.serviceModel section in the Web.Config file.
WF 4.0 no longer requires a
.svc file, but requires the file extension .xamlx on the workflow
definition file for WAS or IIS to host the Workflow Service.
The following configuration snippet applies the basicHttpBinding to the service endpoint matching the service type in the .svc file:
Example 15.
<system.serviceModel> <services> <service name="StandardMold.Services.CustomerService" behaviorConfiguration=" StandardMold.Services. CustomerServiceBehavior"> <endpoint address="..." binding="basicHttpBinding" contract= "StandardMold.QuoteProcess.ICustomerService"> </endpoint> </service> </services> <behaviors> ... </behaviors> </system.serviceModel>
|
Further
compliance configuration options, such as securing the message
transmission over HTTPS or with user credentials, are available in the behaviorConfiguration
section. Hosting Workflow Services in a custom container is supported
as well, but hosting in IIS is generally preferred due to the native
support for enterprise-scale monitoring, process, and management.
Note
Using WF with WCF adds further support for many other WS-* industry standards. For example, applying the wsHttpBinding
to an endpoint configures the message exchange for WS-Security over
HTTP and simply requires a change to the endpoint’s binding in the
Web.Config file, as shown here:
<endpoint address="..." binding="basicHttpBinding"
wsHttpBinding offers a number of behavior settings for security, reliable messaging, and transactions.