Chris
Chris

Reputation: 2481

WCF Call - Best Practice

2 small parts to this question which hopefully will clear up some ambiguity for me.

Firstly, which is better for calling a WCF service?

using (var myService = new ServiceClient("httpBinding")){
     try{         
          var customerDetails = GetCustomerDetails();
          var results = myService.GetCustomerPurchases(customerDetails);
     }catch(Exception e){
          ......
     }
}

or

var myService = new ServiceClient("httpBinding");
try{
     var customerDetails = GetCustomerDetails();
     var results = myService.GetCustomerPurchases(customerDetails);
}catch(Exception e){
     .......
}

What I'm wondering is, should I always be wrapping my service call in a using block? Does IDisposable.Dispose() get called if the service throws an exception?

Upvotes: 2

Views: 5324

Answers (2)

user915331
user915331

Reputation:

Do not use using when dealing with WCF proxies. One of the reasons is Dispose() will call Close() which will throw an exception if the proxy is on Faulted state. So the best use will be something like this:

var myService = new ServiceClient("httpBinding");

try
{
    myService.SomeMethod();
}
catch
{
    // in case of exception, always call Abort*(
    myService.Abort();

    // handle the exception
    MessageBox.Show("error..");
}
finally
{
    myService.Close();
}

Upvotes: 2

Alex Kovanev
Alex Kovanev

Reputation: 1888

Have a look at this question.

Also you can create a couple of classes like

public class ClientService<TProxy>
{
    private static ChannelFactory<TProxy> channelFactory = new ChannelFactory<TProxy>("*");

    public static void SendData(Action<TProxy> codeBlock)
    {
        var proxy = (IClientChannel) channelFactory.CreateChannel();
        bool success = false;

        try
        {
            codeBlock((TProxy)proxy);
            proxy.Close();
            success = true;
        }
        finally
        {
            if (!success)
            {
                proxy.Abort();
            }
        }
    }

    public static TResult GetData<TResult>(Func<TProxy, TResult> codeBlock)
    {
        var proxy = (IClientChannel) channelFactory.CreateChannel();
        bool success = false;

        TResult result;
        try
        {
            result = codeBlock((TProxy)proxy);
            proxy.Close();
            success = true;
        }
        finally
        {
            if (!success)
            {
                proxy.Abort();
            }
        }

        return result;
    }
}

public class SomeAnotherService<TProxy>
{
    public static bool SendData(Action<TProxy> codeBlock)
    {
        try
        {
            ClientService<TProxy>.SendData(codeBlock);
            return true;
        }
        catch(Exception ex)
        {
            //...
        }
        return false;
    }

    public static TResult GetData<TResult>(Func<TProxy, TResult> codeBlock)
    {
        TResult result = default(TResult);
        try
        {
            result = ClientService<TProxy>.GetData(codeBlock);
        }
        catch (Exception ex)
        {
            //...
        }

        return result;
    }
}

Sometimes it's convenient. Here is an example of calling some service method.

var someObj = SomeAnotherService<IMyService>.GetData(x => x.SomeMethod());

Upvotes: 4

Related Questions