Home > .NET, WCF > Closing WCF Service References

Closing WCF Service References

September 1st, 2009 Leave a comment Go to comments

One aspect of using WCF services that took a little bit of time to figure out is the lifespan of the service connection.  Unlike standard web services in .NET, the connection to a WCF service is only closed when the Close method is explicitly called or the service proxy object is disposed.  In the latter case, the normal practice would be to wrap the object in a using statement as below:

using (EmailServiceClient svc = new EmailServiceClient())
{
   svc.SendEmail(fromAddress, fromName, toEmail, toName, message);
}

However, there are problems with the how the Dispose method was implemented that could cause an exception to be thrown and not properly caught as described in this MSDN article: http://msdn.microsoft.com/en-us/library/aa355056.aspx.  Therefore, the best practices dictates that Close is called explicitly and the operations are wrapped in a try/catch block:

EmailServiceClient svc = null;
try
{
   svc = new EmailServiceClient();
   svc.SendMail(fromAddress, fromName, toEmail, toName, message);
   svc.Close();
}
catch (CommunicationException e)
{
   svc.Abort();
}
catch (TimeoutException e)
{
   svc.Abort();
}
catch (Exception e)
{
   svc.Abort();
   throw;
}

Since this is fairly lengthy to write for every service call, I instead added a wrapper class (based on code found in this blog: http://bloggingabout.net/blogs/erwyn/archive/2006/12/09/WCF-Service-Proxy-Helper.aspx).

public class ServiceProxyHelper<TProxy, TChannel> : IDisposable
    where TProxy : ClientBase<TChannel>, new()
    where TChannel : class
{
    ///
    /// Private instance of the WCF service proxy.
    ///
    private TProxy _proxy;

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

    public TChannel Channel { get; private set; }

    ///
    /// Constructs an instance.
    ///
    public ServiceProxyHelper()
    {
        _proxy = new TProxy();
    }

    ///
    /// Disposes of this instance.
    ///
    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;
        }
    }

The new calls to our service now look like this:

using (ServiceProxyHelper<EmailServiceClient, EmailService> svc =
   new ServiceProxyHelper<EmailServiceClient, EmailService>())
{
   svc.Proxy.SendMail(fromAddress, fromName, toEmail, toName, message);
}
Categories: .NET, WCF
  1. No comments yet.
  1. No trackbacks yet.