Workflow Application: How to use a WCF Service as a workflow application with basicHttpBinding or wsHttpBinding

As of version 5.6.2, WorkflowGen includes the WCF Service workflow application, which allows you to declare a WCF Service client proxy .NET class method as a workflow application.

The following example provides instructions on how to create a simple WCF Service with methods used as workflow applications. You can download the Workflow Application WCF Service Sample Pack for the complete sample source code.

Each supported datatype (Text, Numeric, DateTime, File) has a corresponding method. The supported .NET datatypes for each WorkflowGen process data datatype are:

  • Text: String, Char, Byte, SByte, Boolean

  • Numeric: Int16, Int32, Int64, UInt16, UInt32, UInt64, Single, Decimal, Double

  • DateTime: DateTime

  • File: XmlDocument, XmlNode, XmlElement, WorkflowFile

Method

  1. In Visual Studio, create a new .NET WCF Service website/application called WorkflowAppWCFSample under http://localhost/wfgen/WfApps/WebServices.

    Note: WorkflowGen version 5.x.x supports .NET 2.0 and .NET 3.5; WorkflowGen versions 6.x.x and 7.x.x support .NET 4 and .NET 4.5.

  2. Add a reference to WorkflowGen.My.dll v2.3.4 or above (this is only required when you need to exchange files). This library is found in \wfgen\bin and will be included in the WorkflowAppWCFSample website/application’s \bin folder.

    Code: IService.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Runtime.Serialization;
    using System.ServiceModel;
    using System.Text;
    using System.Xml;
    using WorkflowGen.My.Data;
    
    namespace WorkflowAppWCFSample
    {
        [ServiceContract]
        public interface IService
        {
            [OperationContract]
            string GetString(string message);
    
            [OperationContract]
            DateTime GetDateTime(DateTime message);
    
            [OperationContract]
            Double GetDouble(Double message);
    
            [OperationContract, XmlSerializerFormat]
            XmlDocument GetFileXmlDocument(XmlDocument message);
    
            [OperationContract, XmlSerializerFormat]
            XmlNode GetFileXmlNode(XmlNode message);
    
            [OperationContract]
            XmlElement GetFileXmlElement(XmlElement message);
    
            [OperationContract]
        WorkflowFile GetWorkflowFile(WorkflowFile message);
        }
    }
    

    Reference: Workflow Application WCF Service Sample Pack\WCF Service Web Site\WorkflowAppWCFSample\App_Code\IService.cs.

    Code: Service.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Runtime.Serialization;
    using System.ServiceModel;
    using System.Text;
    using System.Xml;
    using WorkflowGen.My.Data;
    
    namespace WorkflowAppWCFSample
    {
        public class Service : IService
        {
            public string GetString(string message)
            {
                return message + "!"
            }
    
            public DateTime GetDateTime(DateTime message)
            {
                return message.AddDays(1);
            }
    
            public Double GetDouble(Double message)
            {
                return message * 10;
            }
    
            public XmlDocument GetFileXmlDocument(XmlDocument message)
            {
                if (WorkflowFile.IsWorkflowFile(message))
                {
                    WorkflowFile file = new WorkflowFile(message);
                    file.Save(@"c:\temp");
                    return file.GetXmlDoc();
                }
                else
                {
                    return message;
                }
            }
    
            public XmlNode GetFileXmlNode(XmlNode message)
            {
                XmlDocument xmlDoc = new XmlDocument();
                xmlDoc.LoadXml(message.OuterXml);
    
                if (WorkflowFile.IsWorkflowFile(xmlDoc))
                {
                   WorkflowFile file = new WorkflowFile(xmlDoc);
                    file.Save(@"c:\temp"); 
                    return file.GetXmlDoc();
                }
                else
                {
                    return message;
                }
            }
    
            public XmlElement GetFileXmlElement(XmlElement message)
            {
                XmlDocument xmlDoc = new XmlDocument();
                xmlDoc.LoadXml(message.OuterXml);
                if (WorkflowFile.IsWorkflowFile(xmlDoc))
                {
                    WorkflowFile file = new WorkflowFile(xmlDoc); 
                    file.Save(@"c:\temp");
                    return file.GetXmlDoc().DocumentElement;
                }
                else
                {
                    return message;
                }
            }
    
            public WorkflowFile GetWorkflowFile(WorkflowFile message)
            {
                message.Save(@"c:\temp"); 
                return message;
            }
        }
    }
    

    Reference: Workflow Application WCF Service Sample Pack\WCF Service Web Site\WorkflowAppWCFSample\App_Code\Service.cs

  3. Update the Service attribute with WorkflowAppWCFSample.Service.

    Code: Service.svc

    <%@ ServiceHost Language="C#" Debug="true" Service="WorkflowAppWCFSample.Service" CodeBehind="~/App_Code/Service.cs" %>
    

    Reference: Workflow Application WCF Service Sample Pack\WCF Service Web Site\WorkflowAppWCFSample\Service.svc

  4. Update the service name attribute with WorkflowAppWCFSample.Service and the contract attribute with WorkflowAppWCFSample.IService.

    Configuration: WorkflowAppWCFSample web.config

    <services>
        <service name="WorkflowAppWCFSample.Service" behaviorConfiguration="ServiceBehavior">
            <endpoint address="" binding="wsHttpBinding" contract="WorkflowAppWCFSample.IService">
            </endpoint>
        </service>
    </services>
    

    Reference: Workflow Application WCF Service Sample Pack\WCF Service Web Site\WorkflowAppWCFSample\Web.config

    Note: By default, this example WCF Service web site/app is configured in Anonymous authentication. For testing, you must enable the Anonymous authentication in IIS for the WorkflowAppWCFSample website/application. We’ll look at the three other authentication methods (Basic, Windows Integrated, and X.509 Certificate) in a later step.

  5. Build the website in Visual Studio.

  6. Create the WCF Service client proxy .NET class using the svcutil tool.

    Reference for svcutil tool: http://msdn.microsoft.com/en-us/library/aa347733(v=vs.110).aspx

  7. In Visual Studio, right-click on Service.svc then choose View in the browser. Note the URL for the WSDL, then run the svcutil tool in a command prompt. This tool will generate a client proxy .NET class Service.cs and configuration file output.config to be used in your WorkflowGen application as a client to call your WCF Service.

    Command prompt

    svcutil.exe http://localhost/wfgen/WfApps/WebServices/WorkflowAppWCFSample/Service.svc?wsdl
    
  8. In Visual Studio, create a new .NET 3.5 Class Library called WorkflowAppWCFSampleTest.

  9. Add a reference to the .NET libraries System.Runtime.Serialization, System.ServiceModel and the WorkflowGen.My v2.3.4 library (\wfgen\bin).

  10. Add the generated client proxy .NET class Service.cs into the project.

  11. Edit the Service.cs file by removing the generated namespace WorkflowGen.My.Data {…} code completely.

  12. Add the IService interface and the rest of the code into a namespace called WorkflowAppWCFSampleTest.

  13. Update the ConfigurationName of the ServiceContractAttribute of the IService interface with WorkflowAppWCFSampleTest.IService".

  14. Compile the WorkflowAppWCFSampleTest project and deploy the WorkflowAppWCFSampleTest.dll into the \wfgen\bin folder.

    Note: If you use Remote Approval, the Web Services API, or the WorkflowGen Engine service to complete workflow actions, you must also copy the DLL into the \wfgen\ws\bin and DRIVE:\Program Files\Advantys\WorkflowGen\Services\bin folders. (For more information, see Workflow Application: Assembly: The assembly system action started but did not complete successfully.)

    See the sample pack for the Service.cs source code.

    Reference: Workflow Application WCF Service Sample Pack\WCF Service Client Proxy\WorkflowAppWCFSampleTest\Service.cs

  15. Configure WorkflowGen for the WCF Service client proxy:

    i. Edit WorkflowGen’s web.config and add the complete <system.serviceModel> node from the output.config file generated in step 5 under the <configuration> node.

    ii. Update the endpoint’s contract attribute with WorkflowAppWCFSampleTest.IService.

    iii. Update the binding’s maxReceivedMessageSize and maxArrayLength attributes with 104857600 (100 MB) to allow large file transfers.

    Configuration: WorkflowGen web.config

    <system.serviceModel>
        <bindings>
            <wsHttpBinding>
                <binding name="WSHttpBinding_IService" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00 bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard maxBufferPoolSize="524288" maxReceivedMessageSize="104857600"messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true" allowCookies="false"&gt;<br />
                <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="104857600  maxBytesPerRead="4096" maxNameTableCharCount="16384" />
                <reliableSession ordered="true" inactivityTimeout="00:10:00" enabled="false" />
                <security mode="Message">
                    <transport clientCredentialType="Windows" proxyCredentialType="None" realm="" />
                    <message clientCredentialType="Windows" negotiateServiceCredential="true" algorithmSuite="Default" establishSecurityContext="true" />
                </security>
            </binding>
        </wsHttpBinding>
    </bindings>
    <client>
        <endpoint address="http://localhost/wfgen/WfApps/WebServices/WorkflowAppWCFSample/Service.svc" binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IService" contract="WorkflowAppWCFSampleTest.IService" name="WSHttpBinding_IService">
        <identity>
            <dns value="localhost" />
        </identity>
        </endpoint>
    </client>
    </system.serviceModel>
    

    Reference: Workflow Application WCF Service Sample Pack\WorkflowGen Configuration\web.config

  16. Configure the WCF Service website/application:

    i. Edit the WorkflowAppWCFSample web.config and add the complete <bindings> node from step 8 above under the <system.serviceModel> node.

    ii. Update the endpoint’s bindingConfiguration attribute with WSHttpBinding_IService

    Configuration: WorkflowAppWCFSample web.config

    <system.serviceModel>
        <bindings>
            <wsHttpBinding>
            <binding name="WSHttpBinding_IService" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard" maxBufferPoolSize="524288" maxReceivedMessageSize="104857600" messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true" allowCookies="false">
                <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="104857600" maxBytesPerRead="4096" maxNameTableCharCount="16384" />
                <reliableSession ordered="true" inactivityTimeout="00:10:00" enabled="false" />
                <security mode="Message">
                    <transport clientCredentialType="Windows" proxyCredentialType="None" realm="" />
                    <message clientCredentialType="Windows" negotiateServiceCredential="true" algorithmSuite="Default" establishSecurityContext="true" />
                </security>
            </binding>
        </wsHttpBinding>
    </bindings>
    <services>
        <service name="WorkflowAppWCFSample.Service" behaviorConfiguration="ServiceBehavior">
            <!-- Service Endpoints -->
            <endpoint address="" binding="wsHttpBinding" contract="WorkflowAppWCFSample.IService" bindingConfiguration="WSHttpBinding_IService">
                <identity>
                    <dns value="localhost"/>
                </identity>
            </endpoint>
            <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
        </service>
    </services>
    <behaviors>
        <serviceBehaviors>
            <behavior name="ServiceBehavior">
                <serviceMetadata httpGetEnabled="true"/>
                <serviceDebug includeExceptionDetailInFaults="false"/>
            </behavior>
        </serviceBehaviors>
    </behaviors>
    </system.serviceModel>
    

    Reference: Workflow Application WCF Service Sample Pack\WCF Service Web Site\WorkflowAppWCFSample\Web.config

    iii. On the Applications screen in the WorkflowGen Administration Module, click New application and configure it as follows:

    • Name: WCFSERVICE_SAMPLE_GET_STRING
    • Description: Returns a string with a !
    • Type: WCF Service
    • Assembly full name or path: WorkflowAppWCFSampleTest

    Click Save.

    • Class full name: Select WorkflowAppWCFSampleTest.ServiceClient

    • Method: Select GetString

    These parameters are automatically generated:

    • IN message (Text)

    • OUT RETURN_VALUE (Text)

You can now use this workflow application in your processes. You can repeat the application creation for each class method to test the other datatypes.

Note: WorkflowGen does not yet support method overload (two methods with the same name but different parameters). This will be supported in a future release.

Notes

Authentication methods

The following authentication methods are supported:

References

http://msdn.microsoft.com/en-us/library/ff647503.aspx

About File parameter

You can send or receive the content of a File to or from your .NET Class Method. There are two ways to do this:

  • If your method uses a WorkflowGen.My.Data.WorkflowFile object:

    public WorkflowFile GetWorkflowFile(WorkflowFile message)
    {
        message.Save("c:\\temp");
        return message;
    }
    
  • If your method uses an XmlDocument, XmlNode, or XmlElement object:

    public XmlDocument GetFile(XmlDocument message)
    {
        if (WorkflowFile.IsWorkflowFile(message))
        {
            WorkflowFile file = new WorkflowFile(message);
            return file.GetXmlDoc();
        }
        else
        {
            return message;
        }
    }
    

In this case your method can convert the XmlDocument, XmlNode, or XmlElement into a WorkflowFile object.

You can use WorkflowFile.IsWorkflowFile() static method to check if the XmlDocument is a WorkflowFile.

Since the file content is stored in memory and sent over the network, you should avoid using these solutions for very large files.