WCF Service Proxy Helper

When you create a Windows Communication Foundation (WCF) service proxy class for a service by using svcutil.exe, it creates a proxy that derives from System.ServiceModel.ClientBase<TChannel>. This class implements IDisposable so you think you can use your proxy safely in a C# using statement and get guaranteed clean-up in the face of exceptions.

However, the System.ServiceModel.ClientBase<TChannel> class can throw exceptions from its Dispose method, because it calls its Close method. This can happen when it is in a faulted state. In that case you have to call Abort for clean-up. Most times you are not interested in knowing whether the Dispose fails or not and you just want to have guaranteed clean up of any resources held by the proxy.

Check out this discussion on the WCF forum for why Microsoft implemented the dispose in this way.

To prevent you from writing a lot of code to accomplish this clean-up, I have written a generic ServiceProxyHelper class that does it for you. You can download it here or view the code below. It only swallows expected exceptions in its Dispose method but it always cleans up by calling Abort.

The idea is that you derive a class from my ServiceProxyHelper<TProxy, TChannel> class. Insert your proxy class (that should derive from ClientBase<TChannel>) name for TProxy, and the service interface name for TChannel. The helper class wraps the proxy and doesn’t directly expose its methods. From your derived class you can use the protected Proxy property to get access to the service proxy. You should add methods to your derived class that delegate to the proxy.

For our project we added convenience method to the derived helper that create request messages and unpack response messages. So our helper methods have a different signature than the methods on the proxy class itself.

This code is provided ”AS-IS” without any warranties. You can change it to fit your needs.

 
using System;
using System.Collections.Generic;
using System.ServiceModel;

namespace LogicaCMG.ServiceAccess
{
    /// <summary>
    /// Generic helper class for a WCF service proxy.
    /// </summary>
    /// <typeparam name="TProxy">The type of WCF service proxy to wrap.</typeparam>
    /// <typeparam name="TChannel">The type of WCF service interface to wrap.</typeparam>
    public class ServiceProxyHelper<TProxy, TChannel>: IDisposable
        where TProxy : ClientBase<TChannel>, new()
        where TChannel : class
    {
        /// <summary>
        /// Private instance of the WCF service proxy.
        /// </summary>
        private TProxy _proxy;

        /// <summary>
        /// Gets the WCF service proxy wrapped by this instance.
        /// </summary>
        protected TProxy Proxy
        {
            get
            {
                if (_proxy != null)
                {
                        return _proxy;
                }
                else
                {
                        throw new ObjectDisposedException("ServiceProxyHelper");
                }
            }
        }

        /// <summary>
        /// Constructs an instance.
        /// </summary>
        protected ServiceProxyHelper()
        {
            _proxy = new TProxy();
        }

        /// <summary>
        /// Disposes of this instance.
        /// </summary>
        public void Dispose()
        {
            try
            {
                if (_proxy != null)
                {
                    if (_proxy.State != CommunicationState.Faulted)
                    {
                        _proxy.Close();
                    }
                    else
                    {
                        _proxy.Abort();
                    }
                }
            }
            catch (CommunicationException)
            {
                _proxy.Abort();
            }
            catch (TimeoutException)
            {
                _proxy.Abort();
            }
            catch (Exception)
            {
                _proxy.Abort();
                throw;
            }
            finally
            {
                _proxy = null;
            }
        }
    }
}

One thought on “WCF Service Proxy Helper”

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>