Derik Whittaker

Syndication

News


Building Async WCF Services in Silverlight with Channelfactory

If you have created any silverlight applications which need to communicate to a WCF Endpoint you know that you must communicate with WCF via Async actions.  As you may know there are multiple ways to get your Silverlight application to communicate with a WCF service.  One way is to simply create a Service Reference, aka proxy.  The other is to use the ChannelFactory and a shared interface. There are many good references on the net on why one is better than the other but personally I prefer to use the ChannelFactory approach as it allows for cleaner separation of concerns and it allows me to share the same interfaces/models on both side of the wire.  Of course this really only works in a closed development scenario, one where you control both sides of the wire.

The issue with using the Channelfactory pattern is that by default it will create synchronous endpoints for use and this is not allowed in Silverlight.  However this problem is easily solved for you and we will take a look at how to solve this.

When you typically setup a WCF OperationContract you typically do something like the following:

[OperationContract]
List<Make> GetMakes();

However as you may have guessed this will create a synchronous method/endpoint when you use the ChanelFactory.  In order to use this in WCF you need to make a slight change to your setup.  You will need to instruct the Contract that you are following the AsyncPattern .  The code below will show you how using the AsyncPattern changes your setup.

[OperationContract(AsyncPattern = true)]
IAsyncResult BeginGetMakes(AsyncCallback callback, object state);
IList<Make> EndGetMakes(IAsyncResult result);

As you can see from above, using the AsyncPattern = true pattern does mean we need to create 2 methods not just 1.  We should take a closer look at these to better understand what is going one.

In the first method we are creating the ‘begin’ call which will return us back a IAsyncResult which will later be provided to the End method.
In the second method we are making a call and passing in the IAsyncResult instance provided to us via the begin call.  It is this second method which will return us back our actual data.

Now that we know how to  create our OperationContract we should take a look at how to create our implementation of these contracts.  The code below will illustrate how to do this

public IAsyncResult BeginGetMakes( AsyncCallback callback, object state )
{
    var db = new AutomobilesEntities();

    var makes = db.Makes.Select( m => new Make {Name = m.Name} ).ToList();

    return new CompletedAsyncResult>(makes);
}

public IList EndGetMakes( IAsyncResult result )
{
    var completedAsyncResult = result as CompletedAsyncResult>;

    return completedAsyncResult != null ? completedAsyncResult.Data : new List();
}

Taking a closer look above you should notice that the Begin method will actually do the ‘heavy’ lifting in terms of performing any real logic.   This method also returns back a AsyncResult class (see below for that class) which will be passed into the ending call The End call.  The End call will accept the provided AsyncResult instance and pull out the data payload inside of it.  It will then pass this payload back as the actual results you were expecting.

Now that we know how to create an Async endpoint how to we spin up an endpoint via the ChannelFactory and make our WCF call work.  Take a look at the code below for that example.

var binding = new BasicHttpBinding(BasicHttpSecurityMode.None)
                              {
                                  MaxBufferSize = 2147483647,
                                  MaxReceivedMessageSize = 2147483647
                              };
            
var endpointAddress = new EndpointAddress(fullEndpointAddress);
var channelFactory = new ChannelFactory(binding, endpointAddress);

var channel = channelFactory.CreateChannel();

AsyncCallback callback = result =>
                                {
                                    var endGetMakes = channel.EndGetMakes(result);

                                    Debug.WriteLine( "I Have Makes" );
                                };

channel.BeginGetMakes(callback, channel);

The magic in the code above which makes this all work is to create the pointer to the AsyncCallback instance and to provide this in your Begin call.

This is the class I used for encapsulating our IAsyncResult

public class CompletedAsyncResult : IAsyncResult
{
    T data;

    public CompletedAsyncResult(T data)
    { this.data = data; }

    public T Data
    { get { return data; } }

    #region IAsyncResult Members

    public object AsyncState
    { get { return (object)data; } }

    public WaitHandle AsyncWaitHandle
    { get { throw new Exception("The method or operation is not implemented."); } }

    public bool CompletedSynchronously
    { get { return true; } }

    public bool IsCompleted
    { get { return true; } }
    #endregion
}

Using the Async Pattern in WCF is a bit more work but it will allow you to do 2 things. 1) Use the Channelfactory in WCF and 2) Create async service calls to allow your application to continue working while you wait for your call to come back.

Till next time,


Posted 12-17-2011 12:23 PM by Derik Whittaker
Filed under: ,

[Advertisement]

Comments

Scott Seely wrote re: Building Async WCF Services in Silverlight with Channelfactory
on 12-18-2011 11:06 AM

The service does NOT need to implement an async contract in order for the client to consume the contract asynchronously. The 'async-ness' is just an implementation detail, informing WCF to create a AsyncMethodInvoker for your OperationContract instead of the normal SyncMethodInvoker. As a matter of fact, when you 'add Service Reference' to your SL project, the async will be handled via event-based handlers, making your life and your code much simpler.

About The CodeBetter.Com Blog Network
CodeBetter.Com FAQ

Our Mission

Advertisers should contact Brendan

Subscribe
Google Reader or Homepage

del.icio.us CodeBetter.com Latest Items
Add to My Yahoo!
Subscribe with Bloglines
Subscribe in NewsGator Online
Subscribe with myFeedster
Add to My AOL
Furl CodeBetter.com Latest Items
Subscribe in Rojo

Member Projects
DimeCasts.Net - Derik Whittaker

Friends of Devlicio.us
Red-Gate Tools For SQL and .NET

NDepend

SlickEdit
 
SmartInspect .NET Logging
NGEDIT: ViEmu and Codekana
LiteAccounting.Com
DevExpress
Fixx
NHibernate Profiler
Unfuddle
Balsamiq Mockups
Scrumy
JetBrains - ReSharper
Umbraco
NServiceBus
RavenDb
Web Sequence Diagrams
Ducksboard<-- NEW Friend!

 



Site Copyright © 2007 CodeBetter.Com
Content Copyright Individual Bloggers

 

Community Server (Commercial Edition)