views:

55

answers:

3

I want to know how to safely call a WCF web service method. Are both of these methods acceptable/equivalent? Is there a better way?

1st way:

public Thing GetThing()
{
    using (var client = new WebServicesClient())
    {
        var thing = client.GetThing();
        return thing;
    }
}

2nd way:

public Thing GetThing()
{
    WebServicesClient client = null;
    try
    {
        client = new WebServicesClient();
        var thing = client.GetThing();
        return thing;
    }
    finally
    {
        if (client != null)
        {
            client.Close();
        }
    }
}

I want to make sure that the client is properly closed and disposed of.

Thanks

+4  A: 

Using using (no pun) is not recommended because even Dispose() can throw exceptions.

Here's a couple of extension methods we use:

using System;
using System.ServiceModel;

public static class CommunicationObjectExtensions
{
    public static void SafeClose(this ICommunicationObject communicationObject)
    {
        if(communicationObject.State != CommunicationState.Opened)
            return;

        try
        {
            communicationObject.Close();
        }
        catch(CommunicationException ex)
        {
            communicationObject.Abort();
        }
        catch(TimeoutException ex)
        {
            communicationObject.Abort();
        }
        catch(Exception ex)
        {
            communicationObject.Abort();
            throw;
        }
    }

    public static TResult SafeExecute<TServiceClient, TResult>(this TServiceClient communicationObject, 
        Func<TServiceClient, TResult> serviceAction)
        where TServiceClient : ICommunicationObject
    {
        try
        {
            var result = serviceAction.Invoke(communicationObject);
            return result;
        } // try

        finally
        {
            communicationObject.SafeClose();
        } // finally
    }
}

With these two:

var client = new WebServicesClient();
return client.SafeExecute(c => c.GetThing());
Anton Gogolev
@Anton, I always create one instance of WebServicesClient and I use it throughout the application instance, does it cause any problem?
Akash Kava
Thanks for this. Didn't expect it to be so complicated, but this looks good.
zod
A: 

Not quite:

nonnb
+1  A: 

The second way is marginally better as you are coping with the fact that an exception might be raised. If you trapped and at least logged the specific exception it would be better.

However, this code will block until GetThing returns. If this is a quick operation then it might not be a problem, but otherwise a better approach is to create an asynchronous method to get the data. This raises an event to indicate completion and you subscribe to that event to update the UI (or what ever it is you need to do).

ChrisF