Logo
programming4us
programming4us
programming4us
programming4us
Home
programming4us
XP
programming4us
Windows Vista
programming4us
Windows 7
programming4us
Windows Azure
programming4us
Windows Server
programming4us
Windows Phone
 
Windows Azure

SOA with .NET and Windows Azure : Process Abstraction and Orchestrated Task Services (part 1) - Workflows Published as ASMX Services

3/29/2011 3:07:38 PM
- Free product key for windows 10
- Free Product Key for Microsoft office 365
- Malwarebytes Premium 3.7.1 Serial Keys (LifeTime) 2019
An orchestrated task service encapsulates a body of business process (workflow) logic and makes it accessible via a published service contract. This section explores the many ways of applying Decoupled Contract with WF as a means of establishing orchestrations as standalone and independently invokable services. We further explore the various industry standards supported by WF, each of which provides different implementation options for the creation of orchestrated task services.

WF relies on the industry standards support provided by WCF and ASMX to position orchestrations as services. The WCF programming model abstracts transports and policies into Send and Receive message exchanges and WF translates this model into corresponding Send and Receive messaging activities. With ASMX, activities can be published and interacted with via WS-I BasicProfile compliant workflows.

A Brief History of WF Service Contract Support

Support for creating technical service contracts improved as WF evolved from version 3.0 to 4.0. With WF 3.0, there was no actual notion of formal contracts. Workflow containers essentially passed opaque Dictionary types to workflow instances in order to move data from the consumer-side to the workflows being positioned as services.

The options for defining formal service contracts for workflows published as a Web service with WF 3.0 were:

  • Define the contract explicitly as a .NET interface and publish the workflow as an ASMX Web service with the “Publish as Web service” feature in Visual Studio. This approach worked for contracts with simple message exchange patterns and limited scalability requirements.

  • Define the contract as an interface following the requirements for WF’s ExternalDataExchange services, and publish the workflow manually. This provided broader support for message exchange patterns and communication protocols, but could require custom development of the service container in order to meet scalability and fault tolerance requirements.

  • Define the contract explicitly as a .NET interface with WCF contract attributes and implement all communication with the workflow via the Receive and Send activities introduced with .NET 3.5. Like the workflow-first option, this approach took advantage of the benefits of WCF, but provided greater flexibility for custom service contract design.

Despite these options, under the covers, WF 3.0 workflows were hosted as in-process services that did not support strongly typed interfaces. It was with version 3.5 of WF Workflow Services that support for formal contracts was introduced. The contract could be defined implicitly with the interface definition dialog introduced in Visual Studio, thereby creating a “workflow-first” approach. Visual Studio 2008 added an Interface designer to define a WCF interface inside the workflow designer and bind the interface to the new Send and Receive activities.

WF 4.0 introduced support for actual contract-first style development with regular WCF service contracts through the use of WCF messaging activities. As a result, workflows themselves can be strongly-typed. Parameters are declared as workflow input or output, either in the Workflow Designer (Figure 1) or in code using the InParameter<T>, OutParameter<T>, and InOutParameter<T> types.

Figure 1. The Workflow Designer in Visual Studio 2010 provides a UI for the definition of workflow parameters.

These parameters can be defined as message types declared in the form of WCF contracts in order to allow for the reuse of contract definitions for in-process services.

Publishing WF Workflows as Web Services and Activities

Because of the diverse options available to apply Decoupled Contract with WF in support of creating orchestrated task services, and because of the importance of choosing the correct option based on your requirements (and the version of WF you are using), we will take the time to explore the details of the following approaches:

  • Workflows Published as ASMX Services

  • Workflows Published via WCF 3.5 Activities

  • Workflows Published via WCF 4.0 Activities

  • Workflows Published via ExternalDataExchange Services

Note that the option you choose can have a significant impact on the application of the Standardized Service Contract principle. In an environment where multiple implementations of WF co-exist, there may be the need to consider Dual Protocols as a means of support for disparate WF service contracts within the same service inventory.

Workflows Published as ASMX Services

Visual Studio offers the “Publish as Web Service” option to expose a body of workflow logic as an ASMX Web service. It requires the definition of a .NET interface that serves as the formal contract for the service. Each interface method maps to either a one-way operation (for methods of type void) or a request-response operation (for methods with a non-void return type).

Note

WF does not require decorating the interface with any special attributes (such as WebMethod) to publish a workflow as a Web service.


The following interface translates to a request-response operation because the method has a non-void return type:

Example 1.
public interface ICustomerService
{
CustomerInfoResponse GetCustomerInfo(
CustomerInfoRequest request);
}
[Serializable]
[XmlRoot(Namespace=
"http://example.org/Service/Customer")]
public class CustomerInfoRequest
{
...
}
[Serializable]
[XmlRoot(Namespace =
"http://example.org/Service/Customer")]
public class CustomerInfoResponse
{
...
}

In the preceding example, WebServiceInputActivity, WebServiceOutputActivity and WebServiceFaultActivity bind a workflow to this interface. Each WebServiceInputActivity corresponds to a method in the interface contract as illustrated in Figure 2.

Figure 2. Service contracts are defined as .NET interfaces. Each interface method maps to a WebServiceInput and possibly a WebServiceOutput activity.

The activity’s InterfaceType and MethodName properties shown in Figure 2 link the activity to the method on the interface. Any method parameters defined by the interface are added to the activity as properties (Figure 3). You can bind them to dependency properties on the workflow to make them available to all other activities.

The WebServiceOutputActivity and the WebServiceFaultActivity handle responses for request-response message exchanges. Figure 3 shows the WF implementation of the interface in Figure 4.

Figure 3. The InterfaceType and MethodName properties configure the service operation for a WebServiceInputActivity.

Figure 4. WebServiceInput and WebServiceOutput bind a workflow to a formal .NET interface contract and allow publishing the workflow as an ASMX service.


The WebServiceInput activity is configured to handle the GetCustomerInfo method and stores the received message in a workflow property. In the example from Figure 4, all logic to collect the customer information is factored into a custom activity. If this custom activity succeeds, then the WebServiceOutput activity sends the response message. Otherwise the WebServiceFault sends an appropriate SOAP fault to the caller.

WF also supports publishing workflows with asynchronous interfaces, such as this one where the SubmitOrder operation does not return anything:

Example 2.
public interface IOrderService
{
void SubmitOrder(OrderDataMessage msg);
}

[Serializable]
[XmlRoot(Namespace = "http://example.org/Service/Order")]
public class OrderDataMessage
{
...
}

Once again, the WebServiceInput activity provides a strongly-typed Web service interface. Figure 5 shows how you can provide a typed service wrapper for an asynchronous service operation.

Figure 5. Asynchronous service operations bind only to a WebServiceInput activity.


After you define the .NET interface and the workflows are developed, you can publish the entire workflow project to an ASMX Web service by selecting “Publish as Web Service” from the context menu in the Solution Explorer or from the Workflow menu (Figure 6).

Figure 6. The project context menu in the Visual Studio solution explorer includes an option to publish a workflow project as an ASMX Web service.


There are some limitations to keep in mind with regard to reusability when deciding between the different options to expose a workflow as a service.

First, the initial release of WF does not provide tools or activities to support formal contracts that express policies beyond the WS-I BasicProfile. With the “Publish as Web Service” feature, workflows are completely decoupled from their external interface and independent of any particular service host. The contract definition does not include any details about message encoding or service policies.

Second, the formal contract definition for the “Publish as Web service” feature lacks control over the XML-related aspects of the service contract, such as the XML namespace of the service, its XML encoding, etc. The generated Web service honors any XML serialization attributes from System.Xml.Serialization on message classes and data classes, but it ignores any attributes you may have put on the interface definition that drives the generation of the WebService-derived class and methods exposed via the WebMethod attribute.

Take the service definition in the following code fragment:

Example 3.
[System.Web.Services.WebService( Namespace =
"http://example.org/QuoteService" )]
public interface SimpleOrderService
{
[System.Web.Services.Protocols.SoapDocumentMethod
(RequestNamespace="http://example.org/Quotes" )]
ns0.QuoteResponse CreateQuote(ns0.QuoteRequest param1);
ns0.ApproveResponse ApproveOrder
(ns0.ApproveRequest quoteData);
ns0.RejectResponse RejectOrder(ns0.RejectRequest quoteData);
}
[System.Xml.Serialization.XmlRoot(
Namespace="http://example.org/Quotes" )]
public class QuoteRequest
{
public Product quoteData;
public Customer customerData;
}

The service interface and the QuoteRequest class are both decorated with attributes to control the XML namespaces of the service and the request data type in the serialized SOAP messages. The generated service, however, does not include the namespace definition for the service. Only the namespace on the CreateQuote element is present:

Example 4.
<soap:Envelope xmlns:xsi=
"http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<CreateQuote xmlns="http://tempuri.org/">
<param1 xmlns="http://example.org/Quotes2">
<quoteData />
<customerData />
</param1>
</CreateQuote>
</soap:Body>
</soap:Envelope>

Because the ability to define namespaces and service types is important to the application of Canonical Schema , let’s cover a work-around whereby we side-step the “Publish as Web Service” option by building the Web service manually.

Start with a Web service class that follows the requirements of WorkflowWebHostingModule to expose a workflow as an ASMX Web service such as the one shown here:

Example 5.
[WebServiceBinding(ConformsTo =
WsiProfiles.BasicProfile1_1, EmitConformanceClaims = true)]
public class OrderService_WebService :
System.Workflow.Activities.WorkflowWebService
{
public OrderService_WebService() :
base(typeof(OrderService))
{
}
[WebMethodAttribute(Description = "SubmitOrder",
EnableSession = false)]
[SoapDocumentMethod(
RequestNamespace="http://example.org/service",
ResponseNamespace="http://example.org/service" )]
public virtual void SubmitOrder(
WorkflowWebService.OrderDataMessage msg)
{
this.Invoke(typeof(WorkflowWebService.IOrderService),
"SubmitOrder", true, new object[] {msg});
}
}

The service class derives from System.Workflow.Activities.WorkflowWebService and each WebMethod marshals the request to the workflow via the Invoke method provided by that base class (similar to what the auto-generated service class would do).

By implementing your own service call, you can add attributes from the System.Web.Services.Protocols namespace to shape the XML of the request and response messages. For example, in the preceding code fragment, we added a SoapDocumentMethod attribute to the XML namespace http://example.org/service instead of the auto-generated namespace for the service’s request and response messages.

Next, you need an .asmx file for ASP.NET to expose the Web service. If you compile the WorkflowWebService class into a separate assembly, the ASMX file would look like this:

<%@WebService Class=
"WorkflowOrchestration.OrderService_WebService"%>

The “Publish as Web Service” option configures the WorkflowWebHostingModule in the Web service’s App.Config file for you. If you choose to bypass this feature and publish the workflow yourself, you have to complete the following steps:

1.
Compile the workflow and the WorkflowWebService derived class into a .NET assembly.

2.
Create an .asmx file to define an endpoint for the WorkflowWebService derived class

3.
Add the WorkflowRuntime section definition for the ASP.NET runtime to parse the WF-specific settings.

4.
Configure the ManualWorkflowSchedulerService and the DefaultWorkflowCommitWorkBatchService services for proper execution of the workflow in the ASP.NET environment.

5.
Add references to the WF assemblies to allow dynamic compilation of the .asmx file.

6.
Configure the WorkflowWebHostingModule, which controls the life cycle of the WorkflowHost in the ASP.NET application.

The following example shows the content you need to add to the configuration file:

Example 6.
  <configSections>
<section name="WorkflowRuntime" type=
"System.Workflow.Runtime.Configuration.
WorkflowRuntimeSection,System.Workflow.Runtime,
Version=3.0.00000.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35" />
</configSections>
<WorkflowRuntime Name="WorkflowServiceContainer">
<Services>
<add type="System.Workflow.Runtime.
Hosting.ManualWorkflowSchedulerService,
System.Workflow.Runtime,Version=3.0.0.0,
Culture=neutral,PublicKeyToken=31bf3856ad364e35"/>
<add type="System.Workflow.Runtime.
Hosting.DefaultWorkflowCommitWorkBatchService,
System.Workflow.Runtime,Version=3.0.0.0,
Culture=neutral,PublicKeyToken=31bf3856ad364e35"/>
</Services>
</WorkflowRuntime>
<system.web>
<compilation debug="false">
<assemblies>
<add assembly="System.Design,Version=2.0.0.0,
Culture=neutral,PublicKeyToken=B03F5F7F11D50A3A"/>
<add assembly="System.Drawing.Design,Version=2.0.0.0,
Culture=neutral,PublicKeyToken=B03F5F7F11D50A3A"/>
<add assembly="System.Transactions,Version=2.0.0.0,
Culture=neutral,PublicKeyToken=B77A5C561934E089"/>
<add assembly="System.Workflow.Activities,
Version=3.0.0.0, Culture=neutral,
PublicKeyToken=31BF3856AD364E35"/>
<add assembly="System.Workflow.ComponentModel,
Version=3.0.0.0, Culture=neutral,
PublicKeyToken=31BF3856AD364E35"/>
<add assembly="System.Workflow.Runtime,
Version=3.0.0.0, Culture=neutral,
PublicKeyToken=31BF3856AD364E35"/>
<add assembly="Microsoft.Build.Tasks,Version=2.0.0.0,
Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A"/>
<add assembly="System.Messaging,Version=2.0.0.0,
Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A"/>
<add assembly="System.Runtime.Remoting,
Version=2.0.0.0, Culture=neutral,
PublicKeyToken=B77A5C561934E089"/>
<add assembly="System.DirectoryServices,
Version=2.0.0.0, Culture=neutral,
PublicKeyToken=B03F5F7F11D50A3A"/>
<add assembly="System.Windows.Forms,
Version=2.0.0.0, Culture=neutral,
PublicKeyToken=B77A5C561934E089"/>
<add assembly="Microsoft.Build.Utilities,
Version=2.0.0.0, Culture=neutral,
PublicKeyToken=B03F5F7F11D50A3A"/>
<add assembly="Microsoft.Build.Framework,
Version=2.0.0.0, Culture=neutral,
PublicKeyToken=B03F5F7F11D50A3A"/>
</assemblies>
</compilation>
...
<httpModules>
<add type="System.Workflow.Runtime.
Hosting.WorkflowWebHostingModule,
System.Workflow.Runtime,Version=3.0.0.0,
Culture=neutral, PublicKeyToken=31bf3856ad364e35"
name="WorkflowHost"/>
</httpModules>
</system.web>
</configuration>


WF does not provide a solution for identifying the target workflow instance for a received message based on the message content. The WorkflowWebHostingModule implements a message correlation solution, but it relies on HTTP Cookies rather than message content, which requires cookie-enabled service consumers (and is an approach discouraged in the WS-I Basic Profile).

A further limitation to keep in mind when selecting ASMX as the hosting environment for WF orchestrations is associated with threading. The ASMX workflow hosting module does not handle overlapping response-request operations because of the way the WorkflowWebHostingModule handles threading. That means you can’t receive messages for an instance while a request-response operation is pending.

The WorkflowWebHostingModule executes the workflow on the ASP.NET thread that handles the Web request—that thread is blocked until the workflow sends the response to the initial request. If the Web server receives another request for that same workflow instance before the outstanding request is sent, the service responds with a SOAP fault.

Unfortunately, you cannot change this behavior without writing your own replacement of the WorkflowWebHostingModule because this module controls the WorkflowHost and manages the WorkflowHost’s life cycle. You can still choose different persistence in the Web service’s Web.Config file, but the WorkflowWebHostingModule hardwires the threading and the scheduling services when you rely on Visual Studio to publish a workflow as an ASMX service. With that limitation in mind, it can be more desirable to design each interaction with the workflow using asynchronous operations.

Other -----------------
- Service-Orientation with .NET : Service Composition and Orchestration Basics - Orchestration (part 2)
- Service-Orientation with .NET : Service Composition and Orchestration Basics - Orchestration (part 1)
- SOA with .NET and Windows Azure : Service Composition 101 (part 2)
- SOA with .NET and Windows Azure : Service Composition 101 (part 1)
- SOA Security with .NET and Windows Azure Security (part 2) - Windows Azure Platform AppFabric Access Control Overview
- SOA Security with .NET and Windows Azure Security (part 1) - Cloud Computing Security 101
- Running a healthy service in the cloud : Better together for scaling
- Running a healthy service in the cloud : Using the service management API (part 4) - Changing configuration and dynamically scaling your application
- Running a healthy service in the cloud : Using the service management API (part 3) - Automating a deployment
- Running a healthy service in the cloud : Using the service management API (part 2) - Listing your services and containers
 
 
Top 10
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Finding containers and lists in Visio (part 2) - Wireframes,Legends
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Finding containers and lists in Visio (part 1) - Swimlanes
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Formatting and sizing lists
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Adding shapes to lists
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Sizing containers
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 3) - The Other Properties of a Control
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 2) - The Data Properties of a Control
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 1) - The Format Properties of a Control
- Microsoft Access 2010 : Form Properties and Why Should You Use Them - Working with the Properties Window
- Microsoft Visio 2013 : Using the Organization Chart Wizard with new data
 
programming4us
Windows Vista
programming4us
Windows 7
programming4us
Windows Azure
programming4us
Windows Server