Windows Workflow Foundation: Calling WCF Services 

Having the ability to call services from inside your workflows is a good thing. Things get a little obfuscated when one wants to expose a WCF based service to Windows Workflow Foundation (WF).

What it comes down to is that currently (beta 2 build of WF) we do not have any built-in workflow activities which would allow you to communicate with the WCF advanced services (meaning WS-Security enabled, TCP based, WS-RM enabled, WS-Tx enabled, ...).

Assuming we have an OrderService exposed using the following config:

<configuration>
  <system.serviceModel>
    <bindings>
      <wsHttpBinding>
        <binding name="Default">
          <security mode="None"/>
        </binding>
        <binding name="Secure">
          <security mode="Message">
            <message clientCredentialType="Windows"/>
          </security>
        </binding>
        <binding name="Reliable">
          <reliableSession enabled="true" ordered="true"/>
        </binding>
      </wsHttpBinding>
    </bindings>
    <services>
      <service name="WCFCalledByWorkflow.OrderService" >
        <endpoint address=""
                  binding="wsHttpBinding"
                  behaviorConfiguration="Default"
                  contract="WCFCalledByWorkflow.IOrderService" />
        <endpoint address="/secure"
                  binding="wsHttpBinding"
                  behaviorConfiguration="Secure"
                  contract="WCFCalledByWorkflow.IOrderService" />
        <endpoint address="/reliable"
                  binding="wsHttpBinding"
                  behaviorConfiguration="Reliable"
                  contract="WCFCalledByWorkflow.IOrderService" />
      </service>
    </services>
  </system.serviceModel>
</configuration>

This, combined with the following hosting app:

using (ServiceHost sh = new ServiceHost(typeof(OrderService),
  
new Uri("http://localhost:666/OrderService")))
{
   sh.Open();
   Console.WriteLine("Order service running..\n");
   Console.WriteLine("Listening on:");
   foreach(ServiceEndpoint se in sh.Description.Endpoints)
   {
      Console.WriteLine(se.Address.ToString());
   }
   Console.WriteLine("\nPress [Enter] to stop the service.");
   Console.ReadLine();
   sh.Close();
}

Would produce the following output when run:

Order service running..

Listening on:
http://localhost:666/OrderService
http://localhost:666/OrderService/secure
http://localhost:666/OrderService/reliable

Press [Enter] to stop the service.

Now, this is not enough. Our service exposes three different endpoints, each one has different message requirements. And what is more important, all three are based on SOAP 1.2 + WS-Addressing.

There is a 'Default' endpoint which is plain vanilla SOAP 1.2 endpoint, without any security (have to mention it: WCF services are secure by default, one has to turn off security to achive this). Second endpoint uses Windows based message security and third turns on WS-RM. Security wise, second and third endpoints are the same (remember, defaults?).

As said, WF is currently not able to communicate with any of the above endpoints. What needs to be done is adding another endpoint to your service, which would expose it in ASMX compatible way.

The new config is this:

<configuration>
  <system.serviceModel>
    <bindings>
      <wsHttpBinding>
        <binding name="Default">
          <security mode="None"/>
        </binding>
        <binding name="Secure">
          <security mode="Message">
            <message clientCredentialType="Windows"/>
          </security>
        </binding>
        <binding name="Reliable">
          <reliableSession enabled="true" ordered="true"/>
        </binding>
      </wsHttpBinding>
    </bindings>
    <services>
      <service name="WCFCalledByWorkflow.OrderService" >
        <endpoint address=""
                  binding="wsHttpBinding"
                  behaviorConfiguration="Default"
                  contract="WCFCalledByWorkflow.IOrderService" />
        <endpoint address="/secure"
                  binding="wsHttpBinding"
                  behaviorConfiguration="Secure"
                  contract="WCFCalledByWorkflow.IOrderService" />
        <endpoint address="/reliable"
                  binding="wsHttpBinding"
                  behaviorConfiguration="Reliable"
                  contract="WCFCalledByWorkflow.IOrderService" />
        <endpoint address="/legacy"
                  binding="basicHttpBinding"
                  contract="WCFCalledByWorkflow.IOrderService"/>
      </service>
    </services>
  </system.serviceModel>
</configuration>

So our Windows Workflow Foundation compatible endpoint is <base address>/legacy.

What this means is that you can bind all your InvokeWebService activities inside workflows to published WCF services by just adding another ASMX compatible endpoint to the WCF service.

The difference in two WCF configs is here:

<endpoint address="/legacy"
   binding="basicHttpBinding"
   contract="WCFCalledByWorkflow.IOrderService"
/>

Code sample can be downloaded here. It includes two projects, a WF and a WCF project. ServiceHost is implemented.

Categories:  .NET 3.0 - WCF | .NET 3.0 - WF
Wednesday, May 31, 2006 11:54:58 AM (Central Europe Standard Time, UTC+01:00)  #    Comments

 

Copyright © 2003-2019 , Matevž Gačnik
Recent Posts
RD / MVP
Feeds
RSS: Atom:
Archives
Categories
Blogroll
Legal

The opinions expressed herein are my own personal opinions and do not represent my company's view in any way.

My views often change.

This blog is just a collection of bytes.

Copyright © 2003-2019
Matevž Gačnik

Send mail to the author(s) E-mail