I'm Keyvan Nayyeri, a 25 years old Ph.D. student at
the Computer Science department of
the University of Texas at San Antonio.
I'm also
a Software Architect and Developer and previously held a B.Sc.
degree in Applied Mathematics.
This is my blog where I publish content about various topics specifically Programming Languages and Compilers, Software
Engineering and Programming.
In one of my recent posts I discussed about Invoking a WebService from a Workflow. The other case is when you want to build a webservice that runs a workflow to return its results. This is the topic of this post but is a little harder than invoking a webservice from a workflow.
Before anything we need a workflow to expose it via our webservice. This step is the main step in building the webservice. First I create a new Sequential Workflow Library project to build my workflow. This workflow does the same job as what my webservice in previous post does: getting a birthdate and returning the age.
There are three built-in workflow activities in Windows Workflow Foundation that play role in building this type of workflows: WebServiceInput, WebServiceOutput and WebServiceFault. In my sample I won't use the last one (WebServiceFault) but it's an activity that you can use to handle any exceptions thrown by your webservice.
WebServiceInput and WebServiceOutput are a pair of activities. First one gets the parameters and second one returns the result (if there is any return value for web methods).
In addition to Name, WebServiceInput has some required properties:
WebServiceOutput has a few required properties as well:
So now I should create an interface for my service. This interface is very simple. You can remember same thing from WCF services, can't you?!
using System;
using System.Collections.Generic;
using System.Text;
namespace ServiceWorkflow
{
public interface IService
{
int GetAge(DateTime BirthDate);
}
}
After this I can step into adding a WebServiceInput to my sequential workflow. I click on "..." button beside InterfaceType textbox to open up "Browse and Select a .NET Type" dialogue. Here I choose IService interface and click on Ok. Next step is to choose the name of my web method (GetAge) from MethodName drop down list. I also must set IsActivating property to True. This is required for first WebServiceInput activity in a workflow. The last step to configure my WebServiceInput is to create a new birthDate member for BirthDate property to keep the value of BirthDate input parameter. This will add an auto-generated code for birthDate member to my workflow code.
Now it's time to add a WebServiceOutput activity to my sequential workflow. After adding this new activity I choose the name of my WebServiceInput activity as value for its InputActivityName property from drop down list and create a new member (named age) for ReturnValue property. This will add an auto-generated code to my workflow code for age member.
After this I have to add my code logic for my GetAge() method. There are two ways to do this:
I'm going to implement the first choice so add a Code activity to my workflow and add my simple logic to its execution.
private void codeActivity1_ExecuteCode(object sender, EventArgs e)
{
int diff = DateTime.Now.Year - this.birthDate.Year;
this.age = (DateTime.Now.Month < this.birthDate.Month ||
((DateTime.Now.Month == this.birthDate.Month)
&& (DateTime.Now.Day < this.birthDate.Day))) ? --diff : diff;
}
So finally my sequential workflow looks like this:
And final code is this:
public sealed partial class AgeServiceWorkflow : SequentialWorkflowActivity
{
public AgeServiceWorkflow()
{
InitializeComponent();
}
public static DependencyProperty birthDateProperty =
DependencyProperty.Register("birthDate", typeof(System.DateTime), typeof(ServiceWorkflow.AgeServiceWorkflow));
[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
[BrowsableAttribute(true)]
[CategoryAttribute("Parameters")]
public DateTime birthDate
{
get
{
return ((System.DateTime)(base.GetValue(ServiceWorkflow.AgeServiceWorkflow.birthDateProperty)));
}
set
{
base.SetValue(ServiceWorkflow.AgeServiceWorkflow.birthDateProperty, value);
}
}
private void codeActivity1_ExecuteCode(object sender, EventArgs e)
{
int diff = DateTime.Now.Year - this.birthDate.Year;
this.age = (DateTime.Now.Month < this.birthDate.Month ||
((DateTime.Now.Month == this.birthDate.Month)
&& (DateTime.Now.Day < this.birthDate.Day))) ? --diff : diff;
}
public static DependencyProperty ageProperty =
DependencyProperty.Register("age", typeof(System.Int32), typeof(ServiceWorkflow.AgeServiceWorkflow));
[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
[BrowsableAttribute(true)]
[CategoryAttribute("Parameters")]
public Int32 age
{
get
{
return ((int)(base.GetValue(ServiceWorkflow.AgeServiceWorkflow.ageProperty)));
}
set
{
base.SetValue(ServiceWorkflow.AgeServiceWorkflow.ageProperty, value);
}
}
}
Now I build my solution to create an assembly and use it in next steps.
Now that I have the workflow for my webservice as an assembly I can create my webservice easily. First I create an ASP.NET Web Service project for my webservice then add three references to my workflow assembly, System.Workflow.Runtime (to be able to run workflow engine inside my webservice) and System.Workflow.Activities (to be able to run workflow activities inside my webservice).
After adding these references, I create a new service but don't use its default implementation (derived from System.Web.Services.WebService). Instead, I derive this service from my workflow (after building the assembly an "_WebService" prefix is added to my class name). I don't add anything else to this service. As it's derived from my workflow it inherits the service behavior from the base class.
using System;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class Service : ServiceWorkflow.AgeServiceWorkflow_WebService
{
public Service()
{
}
}
The last step is to configure my service. I need to add a default Windows Workflow assembly to my HttpModules to manage workflow hosting. System.Workflow.Runtime.Hosting.WorkflowWebHostingModule does this job for me. On the other hand I add a reference to System.Workflow.Runtime.Configuration.WorkflowRuntimeSection inside my <configSections /> element. Configurations for adding the required assemblies to Web.Config are done automatically under <compilation /> element.
<?xml version="1.0"?>
<configuration>
<configSections>
<section name="WorkflowRuntime"
type="System.Workflow.Runtime.Configuration.WorkflowRuntimeSection, System.Workflow.Runtime, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
</configSections>
<appSettings/>
<connectionStrings/>
<system.web>
<httpModules>
<add name="WorkflowHost"
type="System.Workflow.Runtime.Hosting.WorkflowWebHostingModule, System.Workflow.Runtime, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
</httpModules>
<compilation debug="false">
<assemblies>
<add assembly="System.Workflow.Runtime, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
<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"/>
</assemblies>
</compilation>
<authentication mode="Windows"/>
</system.web>
</configuration>
At this point my webservice is ready for testing.
At the end I test my webservice to see if it works.
Now playing: Yanni - Tribute
DotNetKicks.com
Apr 16, 2007 9:07 AM
#
TrackBack
Apr 18, 2007 12:29 AM
#
Windows WorkFlow Foundation is an extreamly handy and usefull way to building workflow type application.
Ajay Solanki
Apr 23, 2007 3:46 AM
#
Keyvan Nayyeri
Apr 23, 2007 4:43 AM
#
Chris Wang
May 09, 2007 10:04 AM
#
kittyCat
Jan 14, 2008 10:14 PM
#
I have been looking for an alternative for Publish as Web Service. Thank you.
However, I havent been able to make it work. I followed the steps but somehow the methods in my workflow library is not exposed as web methods. Do you have the code downloadable? That would really help. Thanks again!!
Srikanth
Nov 13, 2008 6:04 PM
#
I am looking for developing a webservice interface for my workflow. I need to have overloaded methods that would activate the workflow. And I want to use IIS as my workflow runtime host. Now, it seems I can have only one webmethod to activate the workflow. Kindly help how can I have more than one webmethod to activate the workflow.
Workflow Foundation with Webservice interface « IdleThread
Nov 16, 2008 1:43 AM
#
Pingback from Workflow Foundation with Webservice interface « IdleThread
Sandy
Sep 28, 2009 1:29 PM
#
Mike
Nov 24, 2009 6:33 PM
#
Leave a Comment