Basic WCF Services (Part 2)

In the second part of this series I’m going to discuss asynchronous WCF services. If you’re using Silverlight, the runtime enforces the use of async wcf services but there are a number of other scenarios in which async WCF is very beneficial.

The interesting part about asynchronous WCF services is that you only need worry about the async part on one side of the transaction. In a typical client/server model the server can implement the service in a completely synchronous fashion. As such for this example we’re going to use the same service as in the last post. Here it is again. Naturally, it would be hosted in the same fashion as shown last time.

using System.ServiceModel;

[ServiceContract]
public interface IMyService
{
    [OperationContract]
    public void DoSomeWork(bool parameter);

    [OperationContract]
    public int ReturnAnInt();
}

The difference in order to make this service consumable in an asynchronous fashion comes on the client side. This is the standard .Net asynchronous pattern. The interface is similar except that each method on the synchronous service contain two methods on the asynchronous service.

using System.ServiceModel;

[ServiceContract]
public interface IMyService
{
    [OperationContract(AsyncPattern=true)]
    IAsyncResult BeginDoSomeWork(bool parameter, AsyncCallback callback, object obj);

    void EndDoSomeWork(IAsyncResult result);

    [OperationContract(AsyncPattern=true)]
    IAsyncResult BeginReturnAnInt();

    int EndReturnAnInt(IAsyncResult result);
}

A couple things to note about the above interface. First the attributes OperationContract on the methods that will be exposed as services have the AsyncPattern parameter passed to them set to true. This indicates, obviously, that the service is following the async pattern and will work it’s WCF magic to magic this async even thought the server behind the scenes is synchronous. Second for each method on the synchronous service there are two on the async one. One of these methods must start with a ‘Begin’ and the other must start with an ‘End’ followed by the name of the synchronous method. The naming convention used above is not by coincidence. Also notice that both begin methods return an IAsyncResult object and take in an AsyncCallback and object as parameters. Finally, notice that the End methods return type matches the return type of the synchronous method and each takes in an IAsyncResult object as a parameter.

So how do we go about using this async service? The interface in it’s current state is a bit to take in. What we’ll do is wrap this interface in a service class that uses a ChannelFactory object to create the proxies we need to utilize the service. This class can be utilized by registering to the exposed events to be notified when the services you have called are completed.

public class AsyncService
{
    private readonly ChannelFactory<IMyService> channelFactory;
    private readonly IMyService proxy;

    public event EventHandler BeginDoSomeWorkCompleted;

    public event EventHandler<ReturnAnIntEventArgs> BeginReturnAnIntCompleted;

    public AysncService()
    {
        channelFactory = 
            new ChannelFactory<IMyService>(
                new BasicHttpBinding(),
                new EndpointAddress("http://localhost:8080"));

        proxy = channelFactory.CreateChannel();
    }

    public void BeginDoSomeWork(bool parameter)
    {
        proxy.BeginDoSomeWork(parameter, EndDoSomeWork, null);
    }

    private void EndDoSomeWork(IAsyncResult result)
    {
        if (BeginDoSomeWorkCompleted != null)
        {
            BeginDoSomeWorkCompelted(this, EventArgs.Empty);
        }
    }

    public void BeginReturnAnInt()
    {
        proxy.BeginReturnAnInt(EndReturnAnInt, null);
    }

    private int ReturnAnInt(IAysncResult result)
    {
        int res = proxy.EndReturnAnInt(result);

        if (BeginReturnAnIntCompleted != null)
        {
            BeginReturnAnIntCompeted(this,
                new ReturnAnIntEventArgs(res));
        }
    }
}

public class ReturnAnIntEventArgs : EventArgs
{
    public ReturnAnIntEventArgs(int result)
    {
        Result = result;
    }

    public int Result { get; set; }
}

There is a whole lot of stuff going on here. First, we’re using a generic class called ChannelFactory which creates the proxy we need to communicate with our service (MyService). We pass to it a binding, BasicHttpBinding which defines how the services are going to communicate, and we also pass it an endpoint which specified where our service exists. CreateChannel is called on the ChannelFactory object to create the proxy. We then need to implement each member from the interface IMyService. Each Begin method calls the begin method on the proxy and passes to that method a callback to the matching End method as well as a null (which could be a parameter to the End method if you choose). Finally notice in the callback methods, the proxy calls the End method of the interface, passing it the IAsyncResult parameter and it gets back the result casted to the type needed. We then fire an event passing the result of the service call as part of the event args so that subscribers may be notified of the finished async call.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s