If the state machine workflow is required from a cloud application the only way to work around this issue is using HttpWebRequest to generate a REST call via HTTP.. Define a Custom Workf
Trang 1218
officially signed by Microsoft yet (If you use Red Gate’s NET reflector to load the assembly, you will see that it has no strong name key assigned by Microsoft.) If the state machine workflow is required from a cloud application the only way to work around this issue is using HttpWebRequest to generate a REST call via HTTP That is the topic we are going to focus on in the next exercise, which provides an example of a work-around to address the issue
Listing 7-3 Define a Custom Workflow Activity to Send a Notification E-mail When a WCF Call Is Received
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Workflow.ComponentModel;
using System.Workflow.Activities;
using System.Net.Mail;
using System.Diagnostics;
namespace ActivityClassLibrary
{
public class EmailNotificationActivity : Activity
{
public string To { get; set; }
public string From { get; set; }
public string Subject { get; set; }
public string MessageBody { get; set; }
protected override ActivityExecutionStatus Execute(
ActivityExecutionContext executionContext)
{
SmtpClient smtpClient = new SmtpClient();
smtpClient.Host = "smtp.1and1.com";
smtpClient.EnableSsl = false;
smtpClient.UseDefaultCredentials = true;
MailMessage message = new MailMessage(From,
To,
Subject,
MessageBody);
try
{
Trace.WriteLine(
string.Format(" -{0}:Execute, send notification to :{1}",
this.ToString(), To));
smtpClient.Send(message);
}
catch (Exception ex)
{
Trace.WriteLine(
string.Format(" -{0}:Execute, exception caught:{1}",
this.ToString(), ex.Message));
Trang 2219
}
return (ActivityExecutionStatus)ActivityExecutionResult.Succeeded;
}
}
}
Listing 7-4 Host the Workflow with the Custom-Defined Activity from a Worker Role
using System;
using System.Collections.Generic;
using System.Threading;
using System.Linq;
using System.Text;
using Microsoft.ServiceHosting.ServiceRuntime;
using System.ServiceModel;
using System.Workflow.Runtime;
using System.Workflow.ComponentModel;
namespace Workflow WorkerRole
{
using CustomerRegisterNotification;
public class WorkerRole : RoleEntryPoint
{
public override void Start()
{
RoleManager.WriteToLog("Information", "Worker Process entry point called");
using (WorkflowRuntime workflowRuntime = new WorkflowRuntime())
{
AutoResetEvent waitHandle = new AutoResetEvent(false);
workflowRuntime.WorkflowCompleted +=
delegate(object sender, WorkflowCompletedEventArgs e) {
waitHandle.Set();
};
workflowRuntime.WorkflowTerminated +=
delegate(object sender, WorkflowTerminatedEventArgs e) {
Console.WriteLine(e.Exception.Message);
waitHandle.Set();
};
WorkflowInstance instance =
workflowRuntime.CreateWorkflow(
typeof(CustomerRegisterNotificationWorkflow)
);
instance.Start();
waitHandle.WaitOne();
}
while (true)
Trang 3220
{
Thread.Sleep(10000);
RoleManager.WriteToLog("Information", "Working");
}
}
public override RoleStatus GetHealthStatus()
{
// This is a sample worker implementation Replace with your logic
return RoleStatus.Healthy;
}
}
}
Figure 7-5 A custom-defined workflow activity caused the worker role to fail
Trang 4221
Coordinating WF Services Using HttpWebRequest
The NET Framework provides two classes, HttpWebRequest and HttpWebResponse, which are designed to handle communication using HTTP for URIs beginning with http, https, ftp, and file These two
classes with WCF REST support allow us to coordinate WF service applications running in the cloud In this exercise we use HttpWebRequest to communicate with applications running in the cloud and
implement WCF services to support REST queries and drive the activities of a WF service To do so, we implement custom WF activities that must be derived from a System.Workflow.Activities base class
(StateMachineWorkflowActivity) With this exercise, we will learn
• How to compose a WF state machine
• How to implement a WCF service to support a REST query
• How to drive the WF state machine using HttpWebRequest and HttpWebResponse
■ Note The code for this example is in the Exercise 7-2 bundle from the code download
The concept of this solution is shown in Figure 7-6 Since the entire Azure framework is based on
the HTTP paradigm, if WCF client services are hosted in Azure and support HttpWebRequest, then both
on-premises applications and cloud applications can post an HTTP message via HttpWebRequest to
invoke the WCF service running in the cloud; WCF will also drive the workflows through HttpWebRequest
Figure 7-6 Using WCF services hosted in Azure to drive WF workflows via HttpWebRequest and
HttpWebResponse
Trang 5222
Having understood the big picture, let’s get started building a WCF state machine workflow that supports HttpWebRequest In order to be consistent, we use the shopping cart example we used in the previous exercise
■ Note A library WebHttpContext is required for this exercise This library is defined in the
Microsoft.ServiceModel.Samples namespace The source code for this library comes with the source code package of this exercise
1 Create a State Machine Workflow Library project called ShoppingCartWorkflow from Visual Studio (as Figure 7-7 shows) and add a reference to the System.ServiceModel and
System.ServiceModel.Web assemblies
Figure 7-7 Create a state machine workflow library project ShoppingCartWorkflow from Visual Studio
2 Add an interface, IShoppingCartService, to the project This interface is the WCF service contract definition as shown in Listing 7-5 You may notice that the attributes of the operation contracts in the service interface definition are slightly different from those we have used in past chapters The WebInvoke attribute has been attached to each operation contract in order to support HttpWebRequest There are two parameters