Fault-safe WCF Proxy Generator for Service Reference clients

WCF is great, but if a connection ever throws an exception for any reason it puts the client in the Faulted state and the client has to be aborted and recreated. It’s a pain in the ass since this can happen anywhere a client method is called.
In a previous post, I showed the dynamic generation of a proxy for a WCF channel.

Nowadays, I suspect most people create their clients using “Add Service Reference”. This generates a ClientBase client that suffers from the same problem as raw channels – if there’s ever an exception, you need to recreate the instance.

Following the earlier post, I created code to use the CIL Emit libraries to dynamically generate a fault-tolerant proxy around a given client. If an exception is thrown, the client is recreated with the correct authentication and whatever settings were used to construct it in the first place.
The code is up on github.

Dynamically Generating Code at Run-Time with CIL

I want to follow-up on yesterday’s post about the proxy generator with more details about how the code was created and what it does. First, I want to recap the problem I was trying to solve. With .NET web services and WCF, you use a client to connect to a server that implements an interface defining a service contract over a communications channel. As an example, let’s say your service contract does some simple math:

[ServiceContract]
public interface IMathContract : IMathContractBase {

 [OperationContract]
 int Add( int a, int b ); 

 [OperationContract]
 int Subtract( int a, int b );

 [OperationContract]
 int Multiply( int a, int b );

 [OperationContract]
 int Divide( int a, int b );
}

Pretty simple, right? The server’s implementation of the contract is pretty obvious:

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class MathService : IMathContract {

	public int Add( int a, int b ) {
		return a + b;
	}

	public int Subtract( int a, int b ) {
		return a - b;
	}

	public int Multiply( int a, int b ) {
		return a * b;
	}

	public int Divide( int a, int b ) {
		if ( b == 0 ) throw new DivideByZeroException();
		return a / b;
	}
}

The only thing to note here is that if we call Divide with 0 as the denominator, we’re going to get a DivideByZeroException.

Our client is going to connect to the server via a communications channel. Assuming we’ve set up the server’s address and whatnot in the configuration file as “MathEndpoint”, the code to do some basic math looks like this:

ChannelFactory<IMathContract> factory = new ChannelFactory<IMathContract>( "MathEndpoint" );
IMathContract channel = factory.CreateChannel();
Console.WriteLine( "1 + 2 = " + channel.Add( 1, 2 ) );
Console.WriteLine( "4 - 1 = " + channel.Subtract( 4, 1 ) );
Console.WriteLine( "6 / 3 = " + channel.Divide( 6, 3 ) );
Console.WriteLine( "5 * 2 = " + channel.Multiply( 5, 2 ) );

Let’s say we’re worried about that DivideByZero exception so we guard against it.

ChannelFactory<IMathContract> factory = new ChannelFactory<IMathContract>( "MathEndpoint" );
IMathContract channel = factory.CreateChannel();
Console.WriteLine( "1 + 2 = " + channel.Add( 1, 2 ) );
Console.WriteLine( "4 - 1 = " + channel.Subtract( 4, 1 ) );
try {
	Console.WriteLine( "6 / 3 = " + channel.Divide( 6, 0 ) ); // DivideByZeroException
} catch ( Exception ) {
}
Console.WriteLine( "5 * 2 = " + channel.Multiply( 5, 2 ) ); // CommunicationObjectFaultedException!

What happens? Well, even though we caught the exception, having any exception at all put our channel in the Faulted stage and so hen we call the next method, we get a CommunicationObjectFaultedException. Specifically, we get the message:

System.ServiceModel.CommunicationObjectFaultedException: The communication object, System.ServiceModel.Channels.ServiceChannel, cannot be used for communication because it is in the Faulted state.

If we want to keep using our service we have to abort the channel and create another. The fact is, an exception could happen at any time. Here it’s the result of bad input but it could be network timeouts or anything else. We don’t want to wrap every call to our service in a try…catch block capable of resetting our channel. Instead, we want to create a fault-tolerant wrapper or proxy around it.

Here’s a simplified proxy:

public class FaultSafeProxy : IMathContract {

	private readonly ChannelFactory<IMathContract> _factory;
	private IMathContract _channel;

	public FaultSafeProxy( string endpoint ) {
		this._factory = new ChannelFactory<IMathContract>( endpoint );
	}

	#region Channel Management 

	private void Abort() {
		if ( null == this._channel ) return;
		IServiceChannel serviceChannel = (IServiceChannel)this._channel;
		serviceChannel.Abort();
		this._channel = null;
	}

	private void Close() {
		if ( null == this._channel ) return;
		IServiceChannel serviceChannel = (IServiceChannel)this._channel;
		serviceChannel.Close();
		this._channel = null;
	}

	private IMathContract GetChannel() {
		if ( null == this._channel ) {
			this._channel = this._factory.CreateChannel();
		}
		return this._channel;
	}

	#endregion

	#region IMathContract

	public int Add( int a, int b ) {
		try {
			return this.GetChannel().Add( a, b );
		} catch ( Exception ) {
			this.Abort();
			throw;
		}
	}
	// …
	#endregion
}

Not bad, right? If we use our proxy we can call our methods safely:

FaultSafeProxy proxy = new FaultSafeProxy( "MathEndpoint" );
Console.WriteLine( "1 + 2 = " + proxy.Add( 1, 2 ) );
Console.WriteLine( "4 - 1 = " + proxy.Subtract( 4, 1 ) );
try {
	Console.WriteLine( "6 / 3 = " + proxy.Divide( 6, 0 ) ); // DivideByZeroException
} catch ( Exception ) {
}
Console.WriteLine( "5 * 2 = " + proxy.Multiply( 5, 2 ) ); // Works!

So that all being said, our project might have dozens of interfaces and each interface has dozens of methods. How do we want to generate our proxies? We have a few options:

1. By Hand

We could hand-code a proxy for each interface in our project. This has a lot of drawbacks:

  • It’s tedious
  • Every time we add an interface we have to code another proxy
  • Every time we add, remove, or change a method we have to change our proxy.
  • If we ever wanted to change how our proxies worked (to add logging, say), we’d have to go through each class and update it by hand.

It’s pretty obvious that you don’t want to do this if you can avoid it.

2. Statically Generated Code

We could write an EXE that uses reflection to pull our service contracts out of our DLL and generate proxy classes for them. So that we don’t have to know the proxy types ahead of time we could also generate some sort of proxy factory that, given an interface type, could return the correct proxy type. This isn’t bad, but it has some drawbacks too:

  • We would have to run this tool every time we added, removed, or changed a method or interface.
  • Our project would have a lot of generated proxy classes that developers would have to know to ignore.

There’s still one better way, and the topic of this discussion:

3. Dynamically Generated Code

It would be best if we could just say “I want a proxy for IMyServiceContract” and have one handed back no matter what our service contract is. No extra classes. Nothing to maintain. Just a perfect proxy every time. That’s what we’re going to do here.

CIL

It’s pretty well known that .NET languages get compiled down to CIL, the Common Intermediate Language (formerly known as MSIL, or the Microsoft Intermediate Language). It’s less well known that you can actually generate CIL at run time creating whole assemblies in memory to be used just while your code is executing. So how do we do it? The first thing to do is to get an idea of the CIL that you want to generate. First we create a prototype of the class that we want to dynamically create. Our hand-coded proxy, above is a good example. When I compiled that code I got a DLL. Using the IL disassembler tool (which is part of the Microsoft Windows SDK and on my computer was found at C:\Program Files (x86)\Microsoft SDKs\Windows\v8.1A\bin\NETFX 4.5.1 Tools\ildasm.exe) we can have a look.

ildasm

You’re going to want to look at the CIL for the class, constructor, and all the methods in your prototype class. After that, you’re going to start building dynamic code.

Step 1: Create an assembly builder

// Create our dynamic assembly name and version
AssemblyName assemblyName = new AssemblyName( ASSEMBLY_NAME );
assemblyName.Version = new Version( 1, 0, 0, 0 );
// Create the assembly builder, specifying whether we'll want to only run the assembly or run and save it
AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(
	assemblyName,
	//				AssemblyBuilderAccess.Run
	AssemblyBuilderAccess.RunAndSave
	);

Note “Run” vs. “RunAndSave“. If you use “RunAndSave” your assembly will be created on disk, which is useful for debugging. In your final code, you’ll want to just use “Run“.

Step 2: Create a module builder

ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(
	assemblyBuilder.GetName().Name,
	assemblyBuilder.GetName().Name + ".mod"  // Note: A module file name is necessary in order to save
	);

Step 3: Create a type builder


// Define our custom type, which implements the given interface and IDisposable
TypeBuilder typeBuilder = moduleBuilder.DefineType(
GenerateTypeName(),
 TypeAttributes.Class,
 typeof ( Object ),
 interfacesToImplement // type[]
 );

Here we specify our type name, the fact that it’s a class descended from Object, and the interfaces we want to implement.

Step 4: Add members

Now we just want to go through and add our members as we would to create the CIL we saw in the disassembler. Let’s look at our GetChannel method. In C#, it looks like this:

	private IMathContract GetChannel() {
		if ( null == this._channel ) {
			this._channel = this._factory.CreateChannel();
		}
		return this._channel;
	}]
 

In IL, it looks like this:

.method private hidebysig instance class TestProxyGenerator.Prototype.IMathContract
        GetChannel() cil managed
{
  // Code size       47 (0x2f)
  .maxstack  2
  .locals init ([0] class TestProxyGenerator.Prototype.IMathContract CS$1$0000,
           [1] bool CS$4$0001)
  IL_0000:  nop
  IL_0001:  ldnull
  IL_0002:  ldarg.0
  IL_0003:  ldfld      class TestProxyGenerator.Prototype.IMathContract TestProxyGenerator.Prototype.FaultSafeProxy::_channel
  IL_0008:  ceq
  IL_000a:  ldc.i4.0
  IL_000b:  ceq
  IL_000d:  stloc.1
  IL_000e:  ldloc.1
  IL_000f:  brtrue.s   IL_0024
  IL_0011:  nop
  IL_0012:  ldarg.0
  IL_0013:  ldarg.0
  IL_0014:  ldfld      class [System.ServiceModel]System.ServiceModel.ChannelFactory`1<class TestProxyGenerator.Prototype.IMathContract> TestProxyGenerator.Prototype.FaultSafeProxy::_factory
  IL_0019:  callvirt   instance !0 class [System.ServiceModel]System.ServiceModel.ChannelFactory`1<class TestProxyGenerator.Prototype.IMathContract>::CreateChannel()
  IL_001e:  stfld      class TestProxyGenerator.Prototype.IMathContract TestProxyGenerator.Prototype.FaultSafeProxy::_channel
  IL_0023:  nop
  IL_0024:  ldarg.0
  IL_0025:  ldfld      class TestProxyGenerator.Prototype.IMathContract TestProxyGenerator.Prototype.FaultSafeProxy::_channel
  IL_002a:  stloc.0
  IL_002b:  br.s       IL_002d
  IL_002d:  ldloc.0
  IL_002e:  ret
} // end of method FaultSafeProxy::GetChannel

So how do we create that? Let’s go bit by bit. Start with a MethodBuilder and ILGenerator.

MethodBuilder methodBuilder = typeBuilder.DefineMethod(
	"GetChannel",
	MethodAttributes.Private | MethodAttributes.HideBySig,
	CallingConventions.Standard,
	typeof( T ),
	new Type[0]
	);
ILGenerator il = methodBuilder.GetILGenerator();
// Declare local variables
il.DeclareLocal( typeof( T ) );
il.DeclareLocal( typeof( bool ) );

All the IL_00XX values are like GOTO labels and we can define them up front.

// Define some labels ahead of time
Label label0024 = il.DefineLabel();
Label label002D = il.DefineLabel();

Use reflection to get some of the methods outside of our class, in this case ChannelFactory’s CreateChannel method.

// Get some methods ahead of time
MethodInfo channelFactoryCreateChannelMethodInfo = typeof( ChannelFactory<T> ).GetMethod( "CreateChannel", new Type[0] );

Define our locals. This corresponds to

.locals init ([0] class TestProxyGenerator.Prototype.IMathContract CS$1$0000,
[1] bool CS$4$0001)
il.DeclareLocal( typeof( T ) );
il.DeclareLocal( typeof( bool ) );

Then we emit the code that checks if our channel exists

  IL_0000:  nop
  IL_0001:  ldnull
  IL_0002:  ldarg.0
  IL_0003:  ldfld      class TestProxyGenerator.Prototype.IMathContract TestProxyGenerator.Prototype.FaultSafeProxy::_channel
  IL_0008:  ceq
  IL_000a:  ldc.i4.0
  IL_000b:  ceq
  IL_000d:  stloc.1
  IL_000e:  ldloc.1
  IL_000f:  brtrue.s   IL_0024
il.Emit( OpCodes.Nop );
il.Emit( OpCodes.Ldnull );
il.Emit( OpCodes.Ldarg_0 );
il.Emit( OpCodes.Ldfld, this._channelField );
il.Emit( OpCodes.Ceq );
il.Emit( OpCodes.Ldc_I4_0 );
il.Emit( OpCodes.Ceq );
il.Emit( OpCodes.Stloc_1 );
il.Emit( OpCodes.Ldloc_1 );
il.Emit( OpCodes.Brtrue_S, label0024 );

If it doesn’t, we call the factory method to create it:

  IL_0011:  nop
  IL_0012:  ldarg.0
  IL_0013:  ldarg.0
  IL_0014:  ldfld      class [System.ServiceModel]System.ServiceModel.ChannelFactory`1<class TestProxyGenerator.Prototype.IMathContract> TestProxyGenerator.Prototype.FaultSafeProxy::_factory
  IL_0019:  callvirt   instance !0 class [System.ServiceModel]System.ServiceModel.ChannelFactory`1<class TestProxyGenerator.Prototype.IMathContract>::CreateChannel()
  IL_001e:  stfld      class TestProxyGenerator.Prototype.IMathContract TestProxyGenerator.Prototype.FaultSafeProxy::_channel
  IL_0024:  ldarg.0
  IL_0025:  ldfld      class TestProxyGenerator.Prototype.IMathContract TestProxyGenerator.Prototype.FaultSafeProxy::_channel
  IL_002a:  stloc.0
  IL_002b:  br.s       IL_002d
il.Emit( OpCodes.Nop );
il.Emit( OpCodes.Ldarg_0 );
il.Emit( OpCodes.Ldarg_0 );
il.Emit( OpCodes.Ldfld, this._factoryField );
il.Emit( OpCodes.Callvirt, channelFactoryCreateChannelMethodInfo );
il.Emit( OpCodes.Stfld, this._channelField );
il.Emit( OpCodes.Nop );
il.MarkLabel( label0024 );
il.Emit( OpCodes.Ldarg_0 );
il.Emit( OpCodes.Ldfld, this._channelField );
il.Emit( OpCodes.Stloc_0 );
il.Emit( OpCodes.Br_S, label002D );

And finally, we return the channel:

  IL_002b:  br.s       IL_002d
  IL_002d:  ldloc.0
  IL_002e:  ret
 

 

il.MarkLabel( label002D );il.Emit( OpCodes.Ldloc_0 );il.Emit( OpCodes.Ret );

I’m not going to lie. This can be a real pain in the ass to go through and debug. You’ll have to do this for each method you want to generate. Because you’re doing this dynamically, you’ll find yourself using reflection to iterate through the methods that you want to create.If you want to save your assembly to debug your type, this is the time to do it:

assemblyBuilder.Save( assemblyBuilder.GetName().Name + ".dll" );

Step 5: Create the Type and Object

Once you’re done with the TypeBuilder, you’re going to want to create an instance of your new type and that’s easy enough to do:

Type generatedType = typeBuilder.CreateType();
object instance = Activator.CreateInstance( generatedType, endpoint, userName, password );

And that’s it. You’ve got a dynamically generated type. If you made your type implement an interface, like a service contract in our example, you can just cast it to the interface and use the methods on it.

Fault-safe WCF Proxy Generator

In WCF, clients connect to servers using channels that implement a particular service contract interface.  This ordinarily works very well – until something throws an exception.  Let’s say you’re a client, you have some channel object you can cast as IWhatever and you can make calls on its methods.


this._factory = new ChannelFactory<IMathContract>( endpoint );

this._channel = this._factory.CreateChannel();

int c = this._channel.Add( a, b );

If one of those methods throws an error, the channel will become faulted and every subsequent call will throw an exception like “The communication object, System.ServiceModel.Channels.ServiceChannel, cannot be used for communication because it is in the Faulted state.”.  What you have to do now is abort and recreate the channel.  But this error could happen anywhere.  So what we usually do is build a proxy.  The proxy wraps the channel, implementing all the interface’s methods, and aborts the channel if any of these calls throw an exception.


 public int Add( int a, int b ) {
    try {
         return this.GetChannel().Add( a, b );
     } catch ( Exception ) {
         this.Abort();
         throw;
     }
 }

Writing these proxies is tedious, so I’ve created a utility that uses IL generation to dynamically generate a proxy given a service contract.


IMathContract channel = FaultSafeProxyEmitter<IMathContract>.Create( "MockEndpoint" );

This creates a fault-tolerant channel that will abort and reset if an exception is thrown.  The channel will never remain in the Faulted state.  The channel also implements IDisposable to properly close the underlying channel when complete.

The code is up on github.