WCF and the Try-Catch-Abort Pattern






4.13/5 (8 votes)
WCF and the try-catch-abort pattern
Introduction
Proxy Classes are used to talk to Windows Communication Foundation (WCF) Services.
A communication channel is open to the WCF Service that must be closed after the calls to the service.
The proper way to close the communication channel is very important.
The WCF proxy is usually generated using Visual Studio or the svcutil tool.
The generated proxy inherits from a base class System.ServiceModel.ClientBase
that implements the IDisposable
interface.
The service can be called in a using
block that automatically calls the Dispose()
method.
using (MyService client = new MyService())
{
...
} // Dispose is called here
Dispose()
calls the proxy close()
method, that sends a message from the client to the service indicating that the connection session is no longer needed.
A problem can arise with this approach if there is an exception when calling the close()
method. This is why the using
approach is not recommended when calling WCF methods.
If the communication channel is in a faulted state Abort()
should be called and not close()
;
The recommended approach is the Try
-Catch
-Abort
pattern.
This is a simple pattern where a try
...catch
block is used to call the service and in the catch
of an exception, the connection is aborted or closed.
The recommendation by Microsoft in MSDN is:
try
{
...
client.Close();
}
catch (CommunicationException e)
{
...
client.Abort();
}
catch (TimeoutException e)
{
...
client.Abort();
}
catch (Exception e)
{
...
client.Abort();
throw;
}
A generic class for creating and initializing WCF proxy clients can be created to implement the pattern and replace the using
block:
public class WCFProxy
{
public static void Using<t>(Action<t> action)
{
ChannelFactory<t> factory = new ChannelFactory<t>("*");
T client = factory.CreateChannel();
try
{
action(client);
((IClientChannel)client).Close();
factory.Close();
}
catch (Exception ex)
{
IClientChannel clientInstance = ((IClientChannel)client);
if (clientInstance.State == System.ServiceModel.CommunicationState.Faulted)
{
clientInstance.Abort();
factory.Abort();
}
else if (clientInstance.State != System.ServiceModel.CommunicationState.Closed)
{
clientInstance.Close();
factory.Close();
}
throw (ex);
}
}
}
To use the class is as simple as:
WCFProxy.Using((delegate(IMyService client)
{
client.DoWork();
});