ramkasarla

hi

i am in learning stage of WCF and WF, I want to know that

1. while integrating wheather WCF hosts the WF or WF hosts the WCF.

2. Is there any detailed document about how to integrate WCF and WF

3. what are the necessary steps to follow for integration of WCF and WF.

thanks,




Re: Windows Workflow Foundation Steps for integrating WCF and WF

Alan Smith MVP

Hi,

1. Ive looked at this a little with the .net 3 release. As a proof of concept, i built a console app that hosted both the WCF services, and the WF workflow runtime. I implemented code in the WCF services to interace with the WF runtime, and create and manage the workflows.

2. I've not seen any good docs for how to do this with .net 3, but there's a cople of good blog articles on doing this with .net 3.5 beta 1 and Orcas posted by Guy Burstein:

http://blogs.microsoft.co.il/blogs/bursteg/

3. I'd recomend taking a look at beta 1 of Orcas if it's possible in your project. It seems that the new version provides much better OOB integration.

Regards,

Alan





Re: Windows Workflow Foundation Steps for integrating WCF and WF

Jon Flanders

It is certainly possible to integrate WF and WCF today using custom ServiceHosts and invoking workflows directly. I'll be doing a session at TechED US on that topic - http://www.masteringbiztalk.com/blogs/jon/PermaLink,guid,116a206e-db52-41de-afb4-17a6e022e093.aspx and hopefully around that time or soon after that a sample I've built for MS will be made public that relates to WF autohosting in WCF using .NET 3.0 and not Orcas.




Re: Windows Workflow Foundation Steps for integrating WCF and WF

Roman Kiss

ramkasarla,

- Definitely, you should look at the OrcasBeta1 features, that's the primary goal of the .netfx 3.5 - connected systems using these technologies.

- For the current .netfx 3.0 version, the WCF/WF hosting and raising the workflow HEEA event can be really simply like is shown in the following code snippet, service1.svc file:

Code Snippet

<%@ServiceHost
Language=C#
Debug="true"
Service="ServiceTest1"
Factory="RKiss.WorkflowEventService.ServiceHostActivation, WorkflowEventService" %>

// .netfx3
using System;
using System.ServiceModel;
using System.Workflow.Activities;

// WCF/WF integration
using RKiss.WorkflowEventService;

// application specific
using WorkflowLibrary1;


[ServiceContract]
[ServiceBehavior(IncludeExceptionDetailInFaults = true)]
public class ServiceTest1
{
[OperationContract(IsOneWay = true)]
[WorkflowFireEvent(EventType = typeof(IWorkflowEvent))]
public void Approve(object sender, ExternalDataEventArgs e)
{
throw new NotImplementedException();
}
}

where, the Factory attribute of the @ServiceHost enables to integrate WCF hosting with WorkflowRuntime. The following example shows its implementation:

Code Snippet

using System;

using System.Diagnostics;

using System.Collections.Generic;

using System.Text;

using System.Workflow.Runtime;

using System.ServiceModel;

using System.ServiceModel.Activation;

using System.Reflection;

namespace ConsoleApplication1

{

public class WorkflowRuntime2 : WorkflowRuntime, IExtension<ServiceHostBase>

{

public WorkflowRuntime2() : this("WorkflowRuntimeConfig") { }

public WorkflowRuntime2(string configSection) : base(configSection) { }

public void Attach(ServiceHostBase owner)

{

base.StartRuntime();

}

public void Detach(ServiceHostBase owner)

{

if (base.IsStarted)

base.StopRuntime();

}

}

public class ServiceHostActivation : ServiceHostFactoryBase

{

public override ServiceHostBase CreateServiceHost(string constructorString, params Uri[] baseAddresses)

{

return Create(constructorString, baseAddresses);

}

public static ServiceHost Create(string constructorString, params Uri[] baseAddresses)

{

// find the type of the service

Type serviceType = Type.GetType(constructorString, false);

foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())

{

serviceType = assembly.GetType(constructorString, false);

if (serviceType != null)

{

break;

}

}

// validate type

if (serviceType == null)

throw new ArgumentException("Can't find the assembly to create a service type");

return Create(serviceType, baseAddresses);

}

public static ServiceHost Create(Type serviceType, params Uri[] baseAddresses)

{

// create wcf host

ServiceHost host = new ServiceHost(serviceType, baseAddresses);

host.Closing += new EventHandler(host_Closing);

// Service extension for WF

WorkflowRuntime2 workflowRuntime = new WorkflowRuntime2();

// Add the Extension to the ServiceHost collection

host.Extensions.Add(workflowRuntime);

return host;

}

private static void host_Closing(object sender, EventArgs e)

{

WorkflowRuntime wr = (sender as ServiceHost).Extensions.Find<WorkflowRuntime>();

if (wr != null)

{

wr.Dispose();

}

}

}

}

The above servive.svc file also integrates a service operation contract with a workflow contract using the custom WorkflowFireEvent attribute described in the article Fire WorkflowEvent from WCF. This attribute enables to forward the wcf message to the workflow queue.

The service.svc needs to have a web.config file, where are located all metadata for this connected systems:

Code Snippet

<configuration>

<configSections>

<section name="WorkflowRuntimeConfig" type="System.Workflow.Runtime.Configuration.WorkflowRuntimeSection, System.Workflow.Runtime, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>

<section name ="LocalServicesConfig" type ="System.Workflow.Activities.ExternalDataExchangeServiceSection, System.Workflow.Activities, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>

</configSections>

<WorkflowRuntimeConfig >

<Services>

<add type="System.Workflow.Activities.ExternalDataExchangeService, System.Workflow.Activities, Version=3.0.00000.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" ConfigurationSection="LocalServicesConfig" />

<!--<add type="System.Workflow.Runtime.Hosting.ManualWorkflowSchedulerService, System.Workflow.Runtime, Version=3.0.00000.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>-->

<add type="System.Workflow.Runtime.Hosting.SqlWorkflowPersistenceService, System.Workflow.Runtime, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" UnloadOnIdle="true" LoadIntervalSeconds="10" ConnectionString="Initial Catalog=PersistenceStore;Data Source=localhost\SQLEXPRESS;Integrated Security=SSPI;"/>

<add type="System.Workflow.Runtime.Tracking.SqlTrackingService, System.Workflow.Runtime, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" UnloadOnIdle="true" LoadIntervalSeconds="10" ConnectionString="Initial Catalog=TrackingStore;Data Source=localhost\SQLEXPRESS;Integrated Security=SSPI;" />

</Services>

</WorkflowRuntimeConfig>

<LocalServicesConfig>

<Services>

</Services>

</LocalServicesConfig>

<system.serviceModel>

<services>

<service name="ServiceTest1" behaviorConfiguration="MyServiceTypeBehaviors">

<endpoint address="mex" contract="IMetadataExchange" binding="mexHttpBinding"/>

<endpoint address="" contract="ServiceTest1" binding="wsHttpBinding"/>

</service>

</services>

<bindings>

<wsHttpBinding>

</wsHttpBinding>

</bindings>

<behaviors>

<serviceBehaviors>

<behavior name="MyServiceTypeBehaviors" >

<serviceMetadata httpGetEnabled="true" />

</behavior>

</serviceBehaviors>

</behaviors>

</system.serviceModel>

<system.web>

<compilation debug="true">

<assemblies>

<add assembly="System.Workflow.Activities,

Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>

</assemblies>

</compilation>

</system.web>

</configuration>

Thanks

Roman






Re: Windows Workflow Foundation Steps for integrating WCF and WF

kfrost

RKiss,

Do you have a solution for this posted somewhere Or does anybody have an example of the ExpenseReporting V2 service where they've modified it to work with WCF being hosted via IIS

Thanks.






Re: Windows Workflow Foundation Steps for integrating WCF and WF

Marcel de Vries

For easy WCF/WF integration you can also use the Custom activities I published on CodePlex that provide an implementation like the ASMX input and output activities currently in the product. This way you can pick an interface and method you want to implement in your workflow and add a corresponding output activity when you have the results of the service method.

The code will handle workflow instantiation, correlation between input and output and also plugs into the correct workflow runtime you are hosting.

Using these activities will keep you from writing plumbing code yourself and keep your code as clean as possible so you can easily migrate to ORCAS features once they ship.

You can find the docs and samples as http://www.codeplex.com/WCFWorkflow

Regards,

Marcel






Re: Windows Workflow Foundation Steps for integrating WCF and WF

kfrost

Marcel,

Thanks for the post. Questions.

1) Where is the source to these activities Not sure about anybody else but not a good practice to implement components in production posted on the web without the source to be able to troubleshoot and fix in house if necessary I've been looking but have yet to run across the bits behind the activities. Are these available.

2) I would still like to know the process of doing this behind the scenes. MS should put out more real world examples and hosting WCF via IIS seems like a theme of interest. The Expense Reporting V2 example is a pretty decent sample but like most others relies on a console app for hosting which I would contend that not many writing real world apps is going to rely on I'm trying to modify pick through snippets here and there to try and figure out how to configure the web.config etc to get a version of the ExpenseReporting sample to work using IIS as a host

Has anybody already done this and could post Or anybody with experience of integrating WF with WCF possibly be willing to look at the expense reporting example and post the mods necessary. RKiss's post seems to be on the right track but seems to be missing some relavent info to completely get things work.

Thanks.






Re: Windows Workflow Foundation Steps for integrating WCF and WF

Roman Kiss

kfrost,

The following steps are WCF and WF basic integration:

1. Hosting: - WCF and WF hosting is done in the .svc file using the Factory attribute. This is a custom hosting based on the ServiceHostFactoryBase class and its source code can be downloaded from Fire WorkflowEvent from WCF or from this thread - see my previously post.

Code Snippet, service1.svc

<%@ServiceHost
Language=C#
Debug="true"
Service="ServiceTest1"

CodeBehind="~/App_Code/Service1.cs"
Factory="RKiss.WorkflowEventService.ServiceHostActivation, WorkflowEventService" %>

2. Invoking Worfklow in the codeBehind using a Worfklow Local Service:

Code Snippet

[ServiceContract]
public class ServiceTest1 : IMyInterface
{
[OperationContract]
public void Approve(object sender, ExternalDataEventArgs e)
{
// Get reference to the WorkflowRuntime
WorkflowRuntime workflowRuntime = OperationContext.Current.Host.Extensions.Find<WorkflowRuntime>();

// raise event on the Worfklow Local Service

// todo:

}
}

Thanks

Roman






Re: Windows Workflow Foundation Steps for integrating WCF and WF

kfrost

Hey Roman,

Thanks for the post but not using code behind in the svc file. I would imagine anybody writing a production app, the code for the service is in a separate assembly.

I've been trying to piece through your example from your website and I've found links on the Factory setting at.

Thread on IIS hosting

http://forums.microsoft.com/MSDN/ShowPost.aspx PostID=1588040&SiteID=1

@ServiceHost parameters in a svc file.

http://msdn2.microsoft.com/en-us/library/aa967286.aspx

Even still trying to piece meal incomplete code snippets from forums still not happening, getting an error that it can't load specific type. You use ServiceHostFactoryBase but Microsoft examples use just ServiceHostFactory. Not sure why the difference but again, it's fighting through trying to get something to work.

My comments were in hopes that Microsoft was monitoring these threads. It would be nice to have examples such as expenseReporting that mimicked real world. The app and concepts itself are good, but the host as with most, a console app was used which is fine as a for an example that could be followed for hosting via a windows service but Not very helpful when utilizing IIS.

Sure will get through it eventually but it would be nice to have complete relevant examples from Microsoft to cut out the "get through it eventually" portions everytime trying to learn a product from them.

Thanks again for the posts






Re: Windows Workflow Foundation Steps for integrating WCF and WF

Roman Kiss

kfrost,

- To perform IIS/WCF hosting via @ServiceHost directive, the type on the optional attribute Factory must be derived from ServiceHostFactoryBase class in order to call its abstract method:

public abstract ServiceHostBase CreateServiceHost(string constructorString, Uri[] baseAddresses);
where the constructorString parameter is a name of the service type. The method has a responsibility to convert this string to the actually type and returning the ServiceHost reference:
return new ServiceHost(serviceType, baseAddresses);
Additionally, in my custom ServiceHostActivation class, the WorkflowRuntime is attached to the service host.
I think, the problem can be related to the assembly reference or endpoint configuration. Check the assemblies in the /bin folder.
 
Thanks
Roman
 





Re: Windows Workflow Foundation Steps for integrating WCF and WF

Marcel de Vries

well I posted everything on codeplex and there you can download the latest changeset that contains all the sources.(including a sample applciation and step by step guide)

See following link to the latest change set: http://www.codeplex.com/WCFWorkflow/SourceControl/DownloadSourceCode.aspx changeSetId=2184

Also the installer intalls the sources of the activities in the program files/beyondDotNet folder. There you will also find the step by step guide.

Hope that helps,

Regards,

Marcel






Re: Windows Workflow Foundation Steps for integrating WCF and WF

kfrost

Ok, still plugging away at this thing. MS, if you are watching would be tremendously nice if you could post a complete example of this working. Everybody else that has posted, thanks but it's a pain trying to sort through others half posts trying to piece together. Roman, tried to add an IIS host to your example but keep running into nagging glitches you get when you haven't done something before and you have an hour or two here and there per week to try and make sense of a bunch of piece meal.

Looking at it all today, I'm back to the expense reporting example to possibly get it to work. It appears that everything in the wcfextensions file is needed. But when you want utilize IIS as a host, you need to add the factory class as roman has pointed out. What I'm experimenting with now is just adding his code at the bottom of his file like this.

public class ServiceHostActivation : ServiceHostFactoryBase
{
public override ServiceHostBase CreateServiceHost(string constructorString, params Uri[] baseAddresses)
{
return Create(constructorString, baseAddresses);
}

public static ServiceHost Create(string constructorString, params Uri[] baseAddresses)
{
// find the type of the service
Type serviceType = Type.GetType(constructorString, false);

foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
{
serviceType = assembly.GetType(constructorString, false);
if (serviceType != null)
{
break;
}
}

// validate type
if (serviceType == null)
{
throw new ArgumentException("Can't find the assembly to create a service type");
}
return Create(serviceType, baseAddresses);
}

public static ServiceHost Create(Type serviceType, params Uri[] baseAddresses)
{
// create wcf host
ServiceHost host = new ServiceHost(serviceType, baseAddresses);
host.Closing += new EventHandler(host_Closing);

// Service extension for WF Supply Web.Config section with parameters
WfWcfExtension workflowRuntime = new WfWcfExtension("WorkflowRuntimeConfig");

// Add the Extension to the ServiceHost collection
host.Extensions.Add(workflowRuntime);

return host;

}

private static void host_Closing(object sender, EventArgs e)
{
WorkflowRuntime wr = (sender as ServiceHost).Extensions.Find<WorkflowRuntime>();
if (wr != null)
{
wr.Dispose();
}
}
}

Then the svc file looks as such: (To do this you'll need to setup a IIS website and add a wcf service file)

<%@ ServiceHost Language="C#" Debug="true"
Service="ExpenseServices.ExpenseService, ExpenseService"
Factory="WcfExtensions.ServiceHostActivation, WcfExtensions" %>

With the web.config looking like this so far. (May be some kinks with it that I haven't worked out.)

<configuration>
<configSections>
<section name="WorkflowRuntimeConfig" type="System.Workflow.Runtime.Configuration.WorkflowRuntimeSection, System.Workflow.Runtime, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
</configSections>

<WorkflowRuntimeConfig>
<Services>
<add type="System.Workflow.Runtime.Hosting.SqlWorkflowPersistenceService, System.Workflow.Runtime, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" ConnectionString="Initial Catalog=WorkflowPersistence;Data Source=sc430x64-01;Integrated Security=SSPI;"/>
<add type="System.Workflow.Runtime.Tracking.SqlTrackingService, System.Workflow.Runtime, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" ConnectionString="Initial Catalog=WorkflowTracking;Data Source=sc430x64-01;Integrated Security=SSPI;" IsTransactional="false" UseDefaultProfile="true" TrackXomlDocument="True"/>
</Services>
</WorkflowRuntimeConfig>
<system.serviceModel>
<services>
<!-- Before deployment, you should remove the returnFaults behavior configuration to avoid disclosing information in exception messages -->
<service name="ExpenseServices.ExpenseService" behaviorConfiguration="ExpenseServiceBehavior">
<endpoint contract="ExpenseContracts.IExpenseService" binding="wsHttpBinding"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="ExpenseServiceBehavior">
<serviceDebug includeExceptionDetailInFaults="true"/>
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
<appSettings/>
<connectionStrings/>

Trying to get everything to compile and then try to change the Expense and Manager App to utilize the IIS svc and see where it gets me.

I'll post results when I get finished






Re: Windows Workflow Foundation Steps for integrating WCF and WF

kfrost

Roman,

With Expense Reporting with the mods above I'm back to the same problem I had trying to utilize your code in another example. I'm not understanding this intent for this section of code.

foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
{
serviceType = assembly.GetType(constructorString, false);
if (serviceType != null)
{
break;
}
}

// validate type
if (serviceType == null)
{
throw new ArgumentException("Can't find the assembly to create a service type");
}

there are plenty of assemblies but all equate to null and throws an exception. To add to this, if I comment this section of my code then things appear to work. Roman, could you please ellobrate on this section and by chance have any comments as to whether it's needed or not

Thanks.

Can't find the assembly to create a service type

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.ArgumentException: Can't find the assembly to create a service type

Source Error:

Line 113:      if (serviceType == null)
Line 114:      {
Line 115:        throw new ArgumentException("Can't find the assembly to create a service type");
Line 116:      }
Line 117:      return Create(serviceType, baseAddresses);

Source File: C:\Data\TFS\corp-tfs-01\Template\ExpenseReporting\ExpenseReporting\WCFExtensions\WfWcfExtension.cs Line: 115

Stack Trace:






Re: Windows Workflow Foundation Steps for integrating WCF and WF

Roman Kiss

kfrost,

- all assemblies must be in the \bin folder or GAC.

- correct my code by the following code snippet.

Code Snippet - correction
// find the type of the service

Type serviceType = Type.GetType(constructorString, false);

if(serviceType == null)

{

foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())

{

serviceType = assembly.GetType(constructorString, false);

if (serviceType != null)

{

break;

}

}

}

Thanks

Roman






Re: Windows Workflow Foundation Steps for integrating WCF and WF

kfrost

Yes, but why. I wouldn't really care to register the assemblies in the GAC in this case. That wouldn't seem impratical. Plus if I just remove that code, the call into the factory has the correct config string and everything and appears to work if I comment the code out you posted.

What would the code in question here buy me and if it were something important is there another way because registering the assemblies in this case in the GAC would probably not be an option.

Thanks.