Ayende @ Rahien

Refunds available at head office

WCF Async without proxies

I don't like generated proxies for web services, they are generally ugly and not fun to work with. However, up until recently I believed that I had to deal with them if I wanted to use the async operations for web services. As it turn out, I was wrong.

We can actually define an WCF service interface like this:

[ServiceContract]
public interface IAsyncBus
{
	[OperationContract(AsyncPattern = true)]
	IAsyncResult BeginProcess(IMessage[] request, AsyncCallback callback, object asyncState);

	IMessage[] EndProcess(IAsyncResult result);
}

Now you can work with it using:

IAsyncBus bus = new ChannelFactory<IAsyncBus>().CreateChannel();
ar = bus.BeginProcess(...);
//do work
bus.EndProcess(ar);

The problem with that is that on the server side, I also have to do things in an async manner. This is sometimes appropriate, but it tends to be a major PITA for a lot of things.

As it turn out, we can solve the issue with aliasing. In the interface dll, we can define:

[ServiceContract]
public interface IBus
{
	[OperationContract]
	IMessage[] Process(IMessage[] request);
}

[ServiceContract(Name="IBus")]
public interface IAsyncBus
{
	[OperationContract(AsyncPattern = true)]
	IAsyncResult BeginProcess(IMessage[] request, AsyncCallback callback, object asyncState);
	IMessage[] EndProcess(IAsyncResult result);
}

Now, you can create an instance of IAsyncBus to communicate with IBus directory. On the server side, we implement IBus, and handle the message in a synchronous manner. Easy, simple, and doesn't require any proxies :-)

Comments

Rob
03/29/2008 02:54 PM by
Rob

Very nice. I was completely unaware of this.

pb
03/29/2008 04:28 PM by
pb

Outstanding, I'm going to go delete my proxy based code and refactor to this.

Johnny Hall
03/30/2008 08:36 PM by
Johnny Hall

Hi. You might be interested in this alternative to using a proxy or a channel.

http://www.acorns.com.au/blog/?p=113

Ayende Rahien
03/30/2008 08:53 PM by
Ayende Rahien

Johnny,

Actually, I would probably use the Castle's WCF integration facility for this in real scenarios

Johnny Hall
03/30/2008 09:09 PM by
Johnny Hall

That's my preference as well, although I'm not completely familarised with it yet.

It's an interesting piece of code though. I like the approach. I HATE the generated proxies - they're such a p-i-t-a to manage, I find.

Nati Dobkin
04/01/2008 09:05 PM by
Nati Dobkin

Hello,

Async pattern is a nice ability that WCF supplies but as far as I know the server doesn't have to know about the AsyncPattern you are using for your clients.

Your code will work fine without the second contract. For your client you have to declare the AsyncPattern on your service contract mehods and when you implementing it you just have to call the standard Process method – WCF engine will do the rest for you.

You can see implementation of this pattern by running svcutil.exe with your mex address and apply /async parameter on it. You will get fully generated proxy with async pattern implemented for each and every of your contract methods, while in the serve you don’t mention anything about it.

Ayende Rahien
04/01/2008 09:14 PM by
Ayende Rahien

Nati,

The point here is to avoid having to generate a proxy

Nati Dobkin
04/01/2008 09:26 PM by
Nati Dobkin

Hey,

My point was to show that there is no need to write the second contract, like you did. I referenced you to generated code only for proof my concept; you don’t have to use it.

BTW, if you don’t use the generated code and your contract is changed, how do you get the newer one for your client?

Comments have been closed on this topic.