Raza Ali

Raza Ali I am Currently working as an Architect and a Consultant at a Microsoft partner company. I have broad technology interests but find myself more interested in ASP.Net and backend server techonlogies. This blog for me is a means to share whatever I come to learn. Hope you find something useful here.
E-mail me Send mail
MCTS

Recent comments

Recent posts

Files I've Posted

Disclaimer

The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

© Copyright 2010

Sign in

WF session at Nuvica Pakistan

by raza 6/8/2008 10:41:08 PM

On Saturday I delivered an introductory session on WF at the Nuvica Pakistan office. The slides for this session  and the sample code for the series of posts I have written on WF can be found on the Download page. I would welcome all comments on the session and what could we do further in this regard.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: ,

WF | Sessions

Learning WF - Part 10

by raza 6/6/2008 2:05:38 AM

In this installment we will look at the tracking capabilities built into WF. Tracking basically allows you to "log" all the actions your workflows are performing. This includes both the standard trace messages which signal different things such as activities completing, state changes, rule executions exceptions and custom messages placed by the user.

Setting up the WF tracking is quite simple, you just have to add a service to the runtime. Like persistence, there is a ready made service for tracking which can we easily incorporate and should suffice for most cases. Let's add that service now to begin exploring the tracking capabilities. image

We have added the service to our program but we haven't yet setup the database for it. To do that pick up the two script files from C:\<WINDOWS DIR>\ Microsoft.NET\Framework\v3.0\Windows Workflow Foundation\SQL\<LANGUAGE DIR> and run them in the SQL Server database we created previously or in a new database if you like.

The WF runtime does its tracking using what is called a tracking profile. The tracking profile is simply a definition of what needs to be tracked. This tracking profile can be created using the object model or simply as an xml file which can be saved in the database. The default profile from the database looks like this:

<?xml version="1.0" encoding="utf-16" standalone="yes"?>
<TrackingProfile xmlns="http://schemas.microsoft.com/winfx/2006/workflow/trackingprofile" version="1.0.0">
    <TrackPoints>
        <ActivityTrackPoint>
            <MatchingLocations>
                <ActivityTrackingLocation>
                    <Activity>
                        <Type>System.Workflow.ComponentModel.Activity, System.Workflow.ComponentModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35</Type>
                        <MatchDerivedTypes>true</MatchDerivedTypes>

                    </Activity>
                    <ExecutionStatusEvents>
                        <ExecutionStatus>Initialized</ExecutionStatus>
                        <ExecutionStatus>Executing</ExecutionStatus>
                        <ExecutionStatus>Compensating</ExecutionStatus>
                        <ExecutionStatus>Canceling</ExecutionStatus>
                        <ExecutionStatus>Closed</ExecutionStatus>
                        <ExecutionStatus>Faulting</ExecutionStatus>

                    </ExecutionStatusEvents>
                </ActivityTrackingLocation>
            </MatchingLocations>
        </ActivityTrackPoint>
        <WorkflowTrackPoint>
            <MatchingLocation>
                <WorkflowTrackingLocation>
                    <TrackingWorkflowEvents>
                        <TrackingWorkflowEvent>Created</TrackingWorkflowEvent>                       
                        <TrackingWorkflowEvent>Completed</TrackingWorkflowEvent>
                        <TrackingWorkflowEvent>Idle</TrackingWorkflowEvent>
                        <TrackingWorkflowEvent>Suspended</TrackingWorkflowEvent>
                        <TrackingWorkflowEvent>Resumed</TrackingWorkflowEvent>
                        <TrackingWorkflowEvent>Persisted</TrackingWorkflowEvent>
                        <TrackingWorkflowEvent>Unloaded</TrackingWorkflowEvent>
                        <TrackingWorkflowEvent>Loaded</TrackingWorkflowEvent>
                        <TrackingWorkflowEvent>Exception</TrackingWorkflowEvent>
                        <TrackingWorkflowEvent>Terminated</TrackingWorkflowEvent>
                        <TrackingWorkflowEvent>Aborted</TrackingWorkflowEvent>
                        <TrackingWorkflowEvent>Changed</TrackingWorkflowEvent>
                        <TrackingWorkflowEvent>Started</TrackingWorkflowEvent>
                   
</TrackingWorkflowEvents>
                </WorkflowTrackingLocation>
            </MatchingLocation>
        </WorkflowTrackPoint>
        <UserTrackPoint>
            <MatchingLocations>
                <UserTrackingLocation>
                    <Activity>
                        <Type>System.Workflow.ComponentModel.Activity, System.Workflow.ComponentModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35</Type>
                        <MatchDerivedTypes>true</MatchDerivedTypes>
                    </Activity>
                    <Argument>
                        <Type>System.Object, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35</Type>
                        <MatchDerivedTypes>true</MatchDerivedTypes>
                    </Argument>
                </UserTrackingLocation>
            </MatchingLocations>
        </UserTrackPoint>
    </TrackPoints>
</TrackingProfile>

As you can see the workflow tracking profile allows you to trace specific workflows using their type as the matching criteria, plus you can specify if all derived types should be tracked as well. In this case the type Activity has been chosen with derived types, meaning all activities would be tracked. Second, you can track activity execution states and third you can track workflow states. As, for user generated messages they can be anything and produced from anywhere.

Lets create a simple workflow that we want to track.

image

In every code activity we print a message on screen and each delay is of 2 seconds. Lets execute this twice and see what it generates in the database.

image

After the execution of the workflow, lets explore the generated data from top down that is by looking at the workflow first and then the activities within them. If you open the table Workflow you will see a row like this:

image 

This table uniquely lists the workflows that we are tracking. The next level is at the instance of this workflow, for which you should open WorkflowInstance:

image

This table list the individual instances of the particular workflow tracked. There is a field called WorkflowTypeId which links it back to the previous database identifying the workflow type. At the next level we see what events get generated at each workflow instance level:

image

As you can see there are two sets of event lists, representing each instance of execution, and there are fields that link it back to the previous tables. As you can see the progression of data captured, you should be able to relate further information to it. For example, if we open the tables Activities the data should be obvious to us:

image

At the next level:

image

include another reference table in here:

image

and the table next lists down every state the activity went through:

image

I'll leave the database details at this level, so you can explore further.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: , ,

.Net | WF

Learning WF - Part 8

by raza 5/22/2008 11:20:32 AM

In this installment we will be looking at consuming and exposing web services through Workflow Foundation. Needless to say that any modern framework should have the ability to easily interface with web services as more often then not it would either be hosted by a web service or using some.

Let's start with how can you use web service from WF. To consume a web service we need to first create one, use the template provided in visual studio to create a hello world web service. Change the function to accept a parameter called name and say hello to that name.

image3

Now create a sequential workflow that looks like this:

image6

In the first code activity we will get a name from the console and put it in a local property. The value of this property will be bound to the function we are calling in the InvokeWebService activity. The return value is placed in another local property which the second code activity will print.

image9

 image15

image18

Calling web services is as simple as that. When you provide the url for the web service a proxy class is generated as usual and a web reference added.

Now let's come to exposing web service through WF. Yes, it is possible to expose your workflows directly as web services with some visual studio magic. WF designer provides you with three activities, one that allows you to receive the incoming request, the second lets you send a response back to the client and third one alternatively allows you to send back SOAP faults. Think of this web service that you create with WF as a single function in a usual web service implementation where you enter the function with a request and exit with a response or exception. Although it is possible to receive multiple requests and return multiple responses but it is much easier to understand it in such a unit like manner.

Start by dropping a WebServiceInput and WebServiceOutput activity in the workflow. When you get the properties of the input activity, you see the need of an interface and method which these activities will expose. As opposed to previous uses of interfaces to create external services this would just be a plain old interface.

image21

Specify this interface and method in the two activities only that they now need two properties to save the incoming name value and outgoing greeting message. Define these properties and select them here. Once that is done we put in a code activity to make the response message from the incoming name.

 image30

Let's put in a fault activity as well. But we can either return a response for a request or a exception so they have to be put in a exclusive branch. For that let's put a If-Else and put the condition in that if the name is empty it throws the exception that name should be specified. When you put the service fault activity it needs a Fault property to bind to. This needs to be a Exception type of property. Define it and assign it to this activity. We need to instantiate this property to some exception value as well, so for that modify the code activity and add the following line:

image33 

The workflow should look something like this:

image36

Till now we have defined the necessary element to define a web service not the web service itself. Let's do that now by right clicking the project and selecting Publish as Web Service. It may prompt you if the workflow is an application rather than a library. Once published, another project will be added to you solution which actually contains the proxy code for a web service that invokes your workflow and provides it with incoming name and returns the resulting output.

image39

In the web.config you will notice an http handler:

image42

This http module is basically part of the workflow runtime which allows you to do necessary session management for workflow webservices. From previous post you might remember that to send any message to a workflow it is necessary that we talk to it using its unique id. This unique id is available for session management and is stored on the client side in a cookie. So if the client sends a request back with the same id in the cookie then it is considered to be a request for an already running instance of the workflow otherwise a new one is created. All this could be done manually if required without using the built in wizards of visual studio. Select the web service as the startup project and run it.

Lets create a client for it and call this web service. I did it by creating another project in the same solution, adding a web reference to the running service and then selecting this client project as the startup one. Call the method from the service with a name:

image45

It should return the response. Now call it with an empty value:

image48

It should throw an error which says what we specified as the exception description. This ends the post on consuming and exposing web service with WF workflows. In the next post we will learn about workflow persistence, keep reading.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: , ,

.Net | WF

Learning WF - Part 7

by raza 5/14/2008 6:26:00 PM

Till this point we have been working with sequential workflows. Sequential workflows are suitable for all processes where all the "arrows" seem to be pointing in one direction. If you have processes where you may be repeating previously completed steps then you may need what are called state machine workflows. The state machine workflows follow the state machine model which has a number of states linked by transitions. A transition represents an event that triggers the change of state. For any given state there may be N number of transitions resulting in any one of the available states.

This workflow type requires prior understanding of the state machine concept, which I cannot describe in detail here. Let's create a project called LightBulb which has two states, you guessed it right, On and Off. Naturally then we need a "toggle" event for the button which changes the state from one to another. Once the project is created you will see something like this.

This is the initial condition of a state. It allows you to drop a number of activities in it as visible from the diagram. Lets change the name of this state to BulbOff and create another state called BulbOn. Right click on the BulbOff activity and add an EventDriven activity to it. Double click and it should look something like this:

Here lets add a code activity to display a custome message and a SetState activity to change state. The EventDriven activity represents the transition and you can perform whatever actions necessary here during it. At the start you should drop a HandleExternalEvent to catch the transition event. At the end you should do a SetState to change the state to some other activity, otherwise it will stay in the same one.

Lets do the same for the other activity and its SetState should bring us back to this state. Now we need to implement the event that drives both these states. Coincidently in this case its the same event for both on and off, which is the toggle of the switch. Following the previuos post lets define an interface to generate that event.

With this event we set the parameters for both the HandleExternalEvent activities in each state. We can set the same event for both of them because at any given time the workflow will be in one state, hence we can give them difference behaviour. The worflow now looks like the following:

The event properties of the HandleExternalEvent like:

Once this has been taken care of lets write the code to trigger the event and set our workflow rolling. First we need to add this as a service and the write the code to deliver the message to the workflow instance.

The the event delivery code with a bit of twist.

Now when we run it, we see the workflow changing state and executing the code activity. Press escape and it exits.

 Before we end this post lets just look at one more thing, initialization and finalization code. These activities you can add to each state and they will be executed once you enter or leave the state. Lets add both and it should look like this:

 

Add a code activity to each and put a relevant message in there.

In the next post we will look at how to call external web services and expose workflows as web services.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: , ,

.Net | WF

Learning WF - Part 6

by raza 5/10/2008 9:32:00 PM

Let's continue from where we left off, in the current installment we will learn about communicating between host and the workflow instance. Why is this communication important when we can execute any code we want in the workflow? Well, we cannot act on workflow itself to begin with. That's not just it, there are many other scenarios where it is important that we are able to pass information between the hosting program and workflow, for example if the workflow were hosted in a web service. Create a new sequential workflow project called TalkToMe.

 image

Once it is created add new item of the type Interface and call it ICalculator. Communication can take place in two directions, from workflow to host where workflow calls a host function and from host to workflow where host sends the workflow "instance" an event. The key to understanding how communication between host and the workflow works is to understand how workflow communication is designed in general. The services that workflows use from the runtime have actually been separated from the runtime and implemented as independent services which can be added to the runtime and to communicate with these services we need to base these services on interfaces and then use those interfaces to call their functions. Our calculator service will be one such service and we shall now define its interface.

image

Notice the attribute ExternalDataExchange over the interface. This marks the interface usable as runtime service. Next create the implementation for this service right here without adding another file.

 image

Now drop the activity CallExternalMethod and Code to the designer.

image

select the first activity and specify the following details.

 image

The method details are quite obvious except the parameters that we are passing. The IDE has correctly recognized the input values from the selected method and that it has a return value. The input values specified here are static right now but these could be dynamic if we link these values to some value from another activity or link them to properties in the workflow. For the input we used static values but for the return value we must specify some receiving variable. To do that I have defined a property in my workflow and linked it to the return value.

image

This value can now be selected in the return value parameter in properties.

image

We will now use this property in the code activity to print the results.

 image

We can now execute and see the results for it. This covers the scenario where the workflow is communicating with the outside services. How about the outside services talking back to the workflow? To do that we have to define an event and then use a HandleExternalEventActivity to receive the call from outside. Drop this activity from the toolbar to the designer and lets add code to support the callback.

image

Now we have to create the event infrastructure. For that modify the ICalculator interface and add the following event.

 image

I have added an event and a function to raise that event. Notice that I am passing CalcArgs argument to the event handler. To pass any data to the event we need to derive our own class from the ExternalDataEventArgs class.

image

The definition of the event arguments only contains one variable called CalcResult. The constructor points to an important fact about this event handling, which is that the "callback" is bound to a specific instance of the workflow and we need to pass it to the base class here. To acquire this instance ID we need to get it either from within the workflow or where the workflow instance was created. For this example I will get it from the point of creation. In the Program class I have added the following code beside the workflow instance code.

image

After creation of the workflow instance I simply wait for the user to press the enter key and then raise the event to pass information to the workflow instance. Let's look at the implementation code for our event.

image

This goes in the implementation class of the ICalculator interface. Let's go back to our designer to see what have we specified in the properties for the event handler activity.

image

So the activity is receiving an event called CalculationComplete from an ICalculator type class. Notice the "e" parameter, two arguments are passed to any event handler, the sender and the arguments. For the moment we are only interested in receiving the arguments, so for that we create a property in our workflow class for it.

image

And assign this to the "e" parameter.  once the event is called we can get the CalcResult value, which if you look back is 10, and use it other activities.

This concludes the post on host to workflow communication. In the next post we will look at creating state machine workflow and the things that we have learnt here is necessary background for it.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: , ,

.Net | WF

Powered by BlogEngine.NET 1.4.0.0
Theme by Mads Kristensen