The Problem Solver

Tell me and I will forget
Show me and I will remember
Involve me and I will understand
- Confucius -

Google Ads

This Blog

Syndication

Search

Tags

News





  • View Maurice De Beijer's profile on LinkedIn

Community

Email Notifications

Explore

Archives

November 2010 - Posts

By default the WP7 emulator will not react to you typing on the keyboard, instead you have to use the mouse to press keys on the software keyboard that pops up.

image

There is however a hidden feature that will let you use your hardware keyboard, just press Page Up when the software keyboard pops up.

image

And as an extra bonus the three buttons at the bottom of the phone can be activated using F1, F2 and F3 for back, home and search respectively.

 

Cool feature that makes development using the emulator a lot easier Smile

 

Enjoy!

www.TheProblemSolver.nl
Wiki.WindowsWorkflowFoundation.eu

Posted by Maurice | with no comments

One of the cool new features in WCF 4 is the support for WS-Discovery.

 

So what makes WCF Discovery so cool?

Normally when a client application wants to connect to a WCF service it has to know several thing about the service like the operations it supports and where it is located. Knowing the operations at design time makes sense, after all this is functionality you are going to call. But the address makes less sense, that is a deployment things and something we don’t really want to be concerned with at design time. So we can specify the service address in the configuration file of the client app and we can change this as needed. However that does mean that whenever we move the WCF service to a different location, for example a new server, we need to go into each clients configuration file and update it with the new address. Not so nice and error prone as we are manually editing a bunch of XML Sad smile

Decoupling the client from the actual address of the WCF service is what WCF Discovery does meaning we can move our WCF service to a new machine and each client will automatically start using the new address. Now how cool is that? Smile

 

The two modes of WCF Discovery

There are two different ways of using WCF Discovery. The first is add-hoc and is real simple because there is no central server involved and the second being managed which is more capable but also depends on some central service being available. In his post I will be taking a closer look at the simple add-hoc mode.

 

The beauty of add-hoc WCF Discovery

The real nice thing about add-hoc WCF Discovery is that a service can just add a discovery endpoint and the client can check for this whenever it needs to call the service. This is done using the UDP protocol through a broadcast message meaning that a service will just discoverable as long as it is on the same subnet. This means that on lots of cases where a service is used on a LAN this will just work without any extra configuration of a central discovery service. Nice and simple, just the way I like it Smile

 

Adding add-hoc WCF Discovery to a service

To demonstrate how to use add-hoc discovery I wrote a real simple service and self host it using the following code:

using System;
using System.ServiceModel;
 
namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            using (var host = new ServiceHost(typeof(MyService)))
            {
                host.Open();
                Console.WriteLine("The host is listening at:");
                foreach (var item in host.Description.Endpoints)
                {
                    Console.WriteLine("{0}\n\t{1}", item.Address, item.Binding                        );
                }
                Console.WriteLine();
                Console.ReadLine();
            }
        }
    }
 
    [ServiceContract]
    interface IMyService
    {
        [OperationContract]
        string GetData(int value);
    }
 
 
    class MyService : IMyService
    {
        public string GetData(int value)
        {
            var result = string.Format("You entered \"{0}\" via \"{1}\"", 
                value, 
                OperationContext.Current.RequestContext.RequestMessage.Headers.To);
            
            Console.WriteLine(result);
            return result;
        }
    }
}

Note there is nothing about WCF Discovery here at all, it is just a standard WCF service.

 

This WCF service has a configuration file that is almost standard. It exposes the service using three different endpoints, each with a different binding. The WCF Discovery extensions are added by adding an extra endpoint of kind udpDiscoveryEndpoint and the <serviceDiscovery/> element in the service behavior section.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.serviceModel>
    <services>
      <service name="ConsoleApplication1.MyService">
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:9000"/>
            <add baseAddress="net.tcp://localhost:9001/"/>
          </baseAddresses>
        </host>
        <endpoint address="basic"
                  binding="basicHttpBinding"
                  contract="ConsoleApplication1.IMyService" />
        <endpoint address="ws"
                  binding="wsHttpBinding"
                  contract="ConsoleApplication1.IMyService" />
        <endpoint address="tcp"
                  binding="netTcpBinding"
                  contract="ConsoleApplication1.IMyService" />
        <endpoint kind="udpDiscoveryEndpoint" />
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <serviceDiscovery/>
          <serviceMetadata httpGetEnabled="true"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
</configuration>

 

If we run this service it prints a message to the console for each endpoint it is listening on.

image

Most of these endpoints are very standard, it’s the last one urn:docs-oasis-open-org:ws-dd:ns:discovery:2009:01 that stands out and is the UDP discovery endpoint.

 

Using this discovery enabled WCF service from a client application

The first option on the client is to use the DiscoveryClient and have it determine all possible endpoints for the service. This type lives in the System.ServiceModel.Discovery.dll assembly so you will need to add a reference to that first. Using the DiscoveryClient a FindCriteria we can now search for published endpoints and use one like this:

var client = new DiscoveryClient(new UdpDiscoveryEndpoint());
var criteria = new FindCriteria(typeof(IMyService));
var findResult = client.Find(criteria);
 
foreach (var item in findResult.Endpoints)
{
    Console.WriteLine(item.Address);
}
Console.WriteLine();
var address = findResult.Endpoints.First(ep => ep.Address.Uri.Scheme == "http").Address;
Console.WriteLine(address);
var factory = new ChannelFactory<IMyService>(new BasicHttpBinding(), address);
var proxy = factory.CreateChannel();
Console.WriteLine(proxy.GetData(42));
((ICommunicationObject)proxy).Close();

This code will work just fine but there are two problems with it. First of all the client.Find() call will take 20 seconds. The reason is it wants to find as many endpoints as it can and the default time allowed is 20 seconds. You can set this to a shorter time but in that case you run the risk of making the timeout too short and the service not being discovered. The other option is to set the criteria.MaxResults to one so the client.Find() call return as soon as single endpoint is found.
image

The bigger problem here is the binding. I am exposing a BasicHttpBinding, a WSHttpBinding and a NetTcpBinding from my service and the DiscoveryClient doesn’t tell me which binding needs to be used with which address.

 

The DynamicEndpoint to the rescue

There is a different way of using WCF Discovery from the client that is far easier if all we want to do is call a specific service and we don’t really care about all addresses exposed and that is the DynamicEndpoint. Using the DynamicEndpoint we can specify which service we want to call and which binding we want to use and it will just do it for us if there is an endpoint for that binding. The following code calls the service with each of the three bindings supported.

foreach (var binding in new Binding[] { new BasicHttpBinding(), new WSHttpBinding(), new NetTcpBinding() })
{
    var endpoint = new DynamicEndpoint(ContractDescription.GetContract(typeof(IMyService)), binding);
    var factory = new ChannelFactory<IMyService>(endpoint);
    var proxy = factory.CreateChannel();
    Console.WriteLine(proxy.GetData(Environment.TickCount));
    ((ICommunicationObject)proxy).Close();
}

This results in the following output where we can see the different endpoints being used.

image

 

What happens if there is no endpoint with the required binding varies depending on the missing binding. If I remove the BasicHttpBinding from the service and run the client it will find the WSHttpBinding instead and try to call that resulting in a System.ServiceModel.ProtocolException error with message “Content Type text/xml; charset=utf-8 was not supported by service http://localhost:9000/ws.  The client and service bindings may be mismatched.”. The fact that DynamicEndpoint tries to use the address with a different HTTP binding sounds like a bug in WCF Discovery to me. On the other hand removing the WSHttpBinding from the service and running the client produces a much better System.ServiceModel.EndpointNotFoundException error with the message “2 endpoint(s) were discovered, but the client could not create or open the channel with any of the discovered endpoints.”.

 

Conclusion

WCF Discovery is a nice way to decouple clients from the physical address of the service giving us an extra bit of flexibility when deploying our WCF services.

 

Enjoy!

www.TheProblemSolver.nl
Wiki.WindowsWorkflowFoundation.eu

Posted by Maurice | 7 comment(s)

Sometimes you just don’t want to do an Add Service reference in the client application but still be able to to call a WF4 workflow service. The good thing is that a WF4 workflow service is just another WCF service from the client perspective so almost everything you can do with a regular WCF service you can also do with a workflow service. And calling the service without doing an Add Service Reference first is one of those things.

In these examples I am going to use the default workflow service template just to make it easy to get started. Adjust the client code depending on your service contract.

 

The first option is to hand craft the service contract on the client and use the ChannelFactory<T>

This option is very simple and straightforward. Basically you are handcrafting a ServiceContract and request/response MessageContract’s to fit the service.

The ServiceContract is nice and simple and looks like this:

[ServiceContract(Name = "IService")]
interface IMyService
{
    [OperationContract]
    GetDataResponse GetData(GetDataRequest request);
}

 

The request and response messages are defined using a MessageContract like this:

[MessageContract(IsWrapped = false)]
class GetDataRequest
{
    [MessageBodyMember(Name = "int", 
        Namespace = "http://schemas.microsoft.com/2003/10/Serialization/")]
    public int Value { get; set; }
}
 
[MessageContract(IsWrapped = false)]
class GetDataResponse
{
    [MessageBodyMember(Name = "string", 
        Namespace = "http://schemas.microsoft.com/2003/10/Serialization/")]
    public string Value { get; set; }
}

 

With these pieces in place calling the workflow service is simple using the following code:

static void Main(string[] args)
{
 
    var factory = new ChannelFactory<IMyService>(new BasicHttpBinding(), new EndpointAddress("http://localhost:9199/Service1.xamlx"));
    var proxy = factory.CreateChannel();
    var response = proxy.GetData(new GetDataRequest() { Value = 42 });
    Console.WriteLine(response.Value);
    Console.ReadLine();
}

 

Note the only thing that varies here is the endpoint address.

 

Getting rid if the ServiceContract

If you don’t want to use a fixed ServiceContract you can use the low level WCF Message API. In this case we use a very simple service contract with the action name of “*” and request/response of type Message. This means we can send any request to any request/response service through this contract. The contract is very simple:

[ServiceContract]
interface IGenericService
{
    [OperationContract(Action = "*")]
    Message GetData(Message request);
}

 

 

The complexity now is in constructing the messages to send but even that isn’t to bad. There are may ways to do this, I chose the XElement API here but you are free to do it any way you like.

static void Main(string[] args)
{
    XNamespace ns = "http://schemas.microsoft.com/2003/10/Serialization/";
 
    var factory = new ChannelFactory<IGenericService>(new BasicHttpBinding(), new EndpointAddress("http://localhost:9199/Service1.xamlx"));
    var proxy = factory.CreateChannel();
    var request = Message.CreateMessage(MessageVersion.Soap11, "http://tempuri.org/IService/GetData", new XElement(ns + "int", 42));
    
    var response = proxy.GetData(request);
 
    var xml = (XElement)XElement.ReadFrom(response.GetReaderAtBodyContents());
    var message = xml.Value;
    Console.WriteLine("Response is: {0}", message);
 
    Console.ReadLine();
}

 

With this in place you can create a generic client that can send messages to any WCF service, workflow service or plain old WCF, all you need to do is store the endpoint, operation name and message formats somewhere. I have to say I really like this power and have used it in several applications where flexibility and configurability was important.

 

Enjoy!

www.TheProblemSolver.nl
Wiki.WindowsWorkflowFoundation.eu

Posted by Maurice | 1 comment(s)
Filed under: , , , ,

Ron Jacobs showed a number of really cool new workflow features we can be expecting in the next version of Windows Workflow Foundation during the last PDC in Redmond and Tech-Ed Europe in Berlin. One of the new features he demonstrated where the activities we can use to load data from a SQL server database into our workflow. Most of the new features are really cool but the database activities are not.

 

Why don’t I like the new database activities

With the new ExecuteSqlQuery<T> we are back to typing in a literal SQL string to be executed on the server and the related connection string directly into a workflow. Not only does this feel like stepping 5 years back in time, back to plain ADO.NET, it also means that we get no compile time checking or IntelliSense whatsoever. Given that a workflow should be a high level concept this seems pretty harsh.

These days most .NET developers have gotten used to, and expect, the power and beauty or LINQ with the related IntelliSense and compile time checking. The fact that we can’t do so in a workflow but have to revert back to basic ADO.NET as it was released with .NET 1.0 nearly 10 years ago feels bad.

 

What I do like

There are some good parts though. The fact that it uses plain old ADO.NET means it can use the asynchronous model of calling the database, something still very much missing from the Entity Framework today. Another benefit is we can use any ADO.NET provider out there. So no problems reading data from Access or Oracle here.

 

Conclusion

While the async IO and ADO.NET provider model are nice they don’t make up for the big step backwards by not giving us LINQ, IntelliSense and compile time validation of our queries. So I am afraid I have to give this a thumbs down [:(].

 

Enjoy

www.TheProblemSolver.nl
Wiki.WindowsWorkflowFoundation.eu

Posted by Maurice | 2 comment(s)

Windows Workflow Foundation 4 makes it real easy to create workflow services that do long running work on a server. However when we are doing long running work there could be an issue with lots of workflows being started and too many workflow instances competing for the same data and threads thereby causing problems like database timeouts or thread pool starvation.

To simulate a busy workflow service I have the following sample workflow:

image

The workflow service is started using a WCF request, returns a response, prints a start message, does some work and prints a message that it is done. The “long” running work is simulated by this activity:

public class MyActivity : CodeActivity
{
    protected override void Execute(CodeActivityContext context)
    {
        Thread.Sleep(15000);
    }
}

Of course you would never do this for real, just imagine some complex database queries being done instead of a Thread.Sleep() []:)

Adding a simple client application like this:

class Program
{
    static void Main(string[] args)
    {
        for (int i = 0; i < 1000; i++)
        {
            Console.WriteLine("Sending {0}", i);
            var proxy = new ServiceClient();
 
            proxy.Operation1(i);
        }
 
        Console.ReadLine();
    }
}

I originally expected the loop to quickly start 1000 workflows and the workflows to complete after 15 seconds. Turns out this isn’t the case [:(] Even though the SendReply has finished the WCF response is not actually send until the complete workflow is finished. The reason is the workflow will run as many activities as it can before relinquishing control. And that happens to include my Thread.Sleep().

The trick to making the workflow service return the response to the client sooner is to add a Delay activity with a short timeout, I am using 1 second here, just after the SendReply activity. Now the first 115 or so workflows are launched quite quickly and only after the WCF response is returned to the client does the actual work start. The problem is we have over 100 workflows active at the same time and that could be the cause of problems so we want to start throttling our workflows so a limited number runs at the same time.

 

Throttling the Workflow Service

When we are using WCF we can use the serviceThrottling behavior to limit the number of concurrent sessions, request and server instances. The incoming WCF requests for a workflow service respect these throttle limits just like any other WCF service. However after the SendReply we are no longer part of the WCF request handling. However the serviceThrottling maxConcurrentInstances setting is still respected for running workflow service instances. So adding the following to our workflow service behavior would mean no more than 10 workflows are active at any given moment.

<serviceThrottling maxConcurrentInstances="10"/>

This by itself isn’t quite the solution when a client wants to start 1000 workflows as the first 10 will be started and the next can only be started as the first are finished.

 

Creating a batch of Workflow Services

If we want to be able to start 1000 workflows quickly and have them execute with a maximum of 10 at the time we need to add the sqlWorkflowInstanceStore to the mix. By doing this, and increasing the Delay duration a bit we can quickly start 1000 workflows, persist them to disk and unload them. Only when that is done do we allow them to run, a few at the time.

To achieve this I have changed to workflow to the following structure with the Delay set to 10 seconds. You should use a duration that allows you to start all workflow instances before the actual execution starts.

image

With the following configuration file:

<system.serviceModel>
  <behaviors>
    <serviceBehaviors>
      <behavior>
        <serviceMetadata httpGetEnabled="true"/>
        <serviceThrottling maxConcurrentInstances="10"/>
        <sqlWorkflowInstanceStore connectionString="Data Source=.\sqlexpress;Initial Catalog=WorkflowInstanceStore;Integrated Security=True"/>
        <workflowIdle timeToUnload="00:00:00"/>
      </behavior>
    </serviceBehaviors>
  </behaviors>
</system.serviceModel>


The result is 1000 workflows being kicked of quickly, unloaded to SQL Server and then reloaded and executing on their own time, 10 at the time. Sweet for batch jobs kicking off a large number of workflows [:)]

 

Download the code here.

 

Enjoy!

www.TheProblemSolver.nl
Wiki.WindowsWorkflowFoundation.eu

Posted by Maurice | 2 comment(s)
Filed under: , , , ,

In my previous WF4 post I described the principal of how to version workflow services using the WCF 4 RoutingService. In that post I described the general problem and solution without going into a lot of detail and showing any code. In this blog post I will add an actual implementation you can use for reference purposes.

 

The basic layout

The solution has three parts.

  1. The workflow service with 2 different versions of same workflow. The second version of the workflow has more activities in the tree so it can’t load workflow instances from version 1. Each workflow is hosted in a different XAMLX file and the second was created by copying the first and making the required changes to it.
  2. The client application that is calling the service. It knows about one existing workflow instance previously created and will create a new one. Next it will send several requests to both workflows without knowing that these are implemented using different version.
  3. The routing service which receives all requests from the client and forwards them to the different workflow services depending on the data in the request.

 

The Workflow Services

image

The workflow version 1

image

The workflow version 2

 

The client application

The basic setup is that the first request, creating the new workflow instance, returns the version identifier and this is a mandatory item in each subsequent request. The client code that does this looks like this:

 

using System;
using TheClient.ServiceReference1;
 
namespace TheClient
{
    class Program
    {
        static void Main(string[] args)
        {
            var proxy = new ServiceClient();
 
            var version = proxy.StartOrder(2);
 
            for (int i = 0; i < 5; i++)
            {
                Console.WriteLine(proxy.AddItem(1, "1.0"));
                Console.WriteLine(proxy.AddItem(2, version));
            }
 
            proxy.Stop(2, version);
 
            Console.ReadLine();
        }
    }
}

Along with this config file:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.serviceModel>
    <client>
      <endpoint address="http://localhost:8080/Service"
                binding="basicHttpBinding"
                contract="ServiceReference1.IService"
                name="BasicHttpBinding_IService" />
    </client>
  </system.serviceModel>
</configuration>

The address “http://localhost:8080/Service” used here is the address of the routing service.

 

The WCF RoutingService

This is where the magic really happens. It checks the versionId parameter from each request and sends the request to the corresponding service. And if no version is found, i.e. a new workflow is started, the request is routed to the last version.

 

The code is pretty simple and looks like this:

using System;
using System.ServiceModel;
using System.ServiceModel.Routing;
 
namespace TheRouter
{
    class Program
    {
        static void Main(string[] args)
        {
            var host = new ServiceHost(
                typeof(RoutingService), 
                new Uri("http://localhost:8080/Service"));
 
            host.Open();
 
            Console.WriteLine("The RoutingService is listening");
            Console.ReadLine();
            
            host.Close();
        }
    }
}

 

Most of the work is done in the configuration file:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.serviceModel>
    <client>
      <endpoint address="http://localhost:26606/Service_V1.xamlx"
                binding="basicHttpBinding"
                contract="*"
                name="serviceV1"/>
      <endpoint address="http://localhost:26606/Service_V2.xamlx"
                binding="basicHttpBinding"
                contract="*"
                name="serviceV2"/>
    </client>
    <services>
      <service name="System.ServiceModel.Routing.RoutingService">
        <endpoint address=""
                  binding="basicHttpBinding"
                  contract="System.ServiceModel.Routing.IRequestReplyRouter"/>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <routing filterTableName="serviceRouting"
                   routeOnHeadersOnly="false"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <routing>
      <filters>
        <filter filterType="XPath"
                name="serviceV1"
                filterData="//ns:versionId='1.0'"/>
        <filter filterType="XPath"
                name="serviceV2"
                filterData="//ns:versionId='2.0'"/>
        <filter filterType ="MatchAll"
                name="all"/>
      </filters>
      <namespaceTable>
        <add prefix="ns"
             namespace="http://tempuri.org/"/>
      </namespaceTable>
      <filterTables>
        <filterTable name="serviceRouting">
          <add endpointName="serviceV1"
               filterName="serviceV1"
               priority="2"/>
          <add endpointName="serviceV2"
               filterName="serviceV2"
               priority="2"/>
          <add endpointName="serviceV2"
               filterName="all"
               priority="1"/>
        </filterTable>
      </filterTables>
    </routing>
  </system.serviceModel>
</configuration>

 

 

Running this shows the following output showing that the different requests where send to the correct workflow

image 

 

You can download the complete VS2010 solution with all code here.

 

Enjoy!

www.TheProblemSolver.nl
Wiki.WindowsWorkflowFoundation.eu

Posted by Maurice | 5 comment(s)
Filed under: , , , ,

One of the problems with the current version of Windows Workflow Foundation is how to handle different versions of your workflows. With short running workflows this is no big deal, workflows do whatever they are supposed to do and finish, and you can deploy a newer updated version of your XAMLX files whenever you want. Provided the public facing SOAP interface doesn’t change no one will notice a difference and everything will work just fine.

However as soon as we get into long running workflows and the SQL Workflow Instance Store things get quite a bit more complicated. As soon as you add or remove activities from your XAMLX, the workflow service definition, you can no longer load any of the workflow instances currently saved in the SQL Workflow Instance Store. This is a bit of a problem because it would mean you would either have to wait until all workflows are finished before upgrading you workflow definition or you would have to abort all running instances, neither is an acceptable solution in most cases.

image

 

How workflow data is stored

The SQL Workflow Instance Store keeps track of the WCF address used to start a workflow and stores that along with the actual workflow state. It uses this data to differentiate between different workflow service definition. And this can actually help us fixing our versioning problem, just leave the existing workflow definition as is and create a new one alongside it with the new definition.

image

So this solves the problem of separating the state of each workflow version but means that the client application needs to be updated each time a new version of the workflow service is deployed. Not only that but the client needs to keep track of which workflow was started using which service and send each future requests to the same address. This puts a big extra burden on our client app and that is something we don’t want.

 

The WCF 4 RoutingService to the rescue

We can solve this problem by adding the WCF RoutingService, a new .NET 4 feature, to the mix. In this case the client only talks to the routing service and the routing service is aware of each workflow service version and knows how to route the request to the correct address. This way the client never knows when new workflow services are created, all it knows about is the WCF RoutingService address.

image

 

So how does the WCF RoutingService where to send messages?

There are several ways this can be done but the easiest is to have the workflow service return a version number from the initial request that started the workflow. This version number is also a required argument for each subsequent request into the workflow. The WCF RoutingService can now use this version part of the message, or the lack thereof, to determine where to route the message. If there is no version information the message is always routed to the last version of the workflow service so new instance requests as well as WSDL requests are always send to the most recent version.

 

So does this solve all our problems?

Unfortunately not. This will solve the problem of updating the workflow service definition and keeping the different versions apart it does keep the workflow already running with their old definition. And that might be exactly what you want in some cases but if there is a bug in the existing definition you still can’t fix that. And that is a problem that can’t really be solved properly with WF4. This feature has been promised at the 2010 PDC for the next version of .NET but that doesn’t help us now.

 

Enjoy!

 

www.TheProblemSolver.nl
Wiki.WindowsWorkflowFoundation.eu

Posted by Maurice | 2 comment(s)
Filed under: , , , , ,