Disposing/Cleaning up web service proxies
Asked Answered
G

1

5

What is the best practise for Disposing/Cleaning up a web service proxy instance after synchronous usage?

How does the answer differ if the proxy class is derived from SoapHttpClientProtocol versus ClientBase<T>?

Background

I'm trying to figure out why one of my WCF web services sometimes seems to get into a state where it no longer reponds to service calls. Basically it seems like it hangs and for now I don't really have any hard data to figure out what's going on when this occurrs.

One thing that I suspect might be an issue is the fact that this WCF service is itself doing web service calls to a few other services. These other services are called (synchronously) using proxies that are derived from SoapHttpClientProtocol (made using wsdl.exe) and at this time these proxy instances are left to be cleaned up by the finalizer:

...
var testProxy = new TestServiceProxy();
var repsonse = testProxy.CallTest("foo");

// process the reponse
...

So should I simply wrap these up in a using(...) { ... } block?

...
using(var testProxy = new TestServiceProxy())
{
    var repsonse = testProxy.CallTest("foo");

    // process the reponse
}
...

What if I were to change these proxy classes to be based on ClientBase<T> by recreating them using svcutil.exe? Based on my research so far, it seems the Dipose() method of classes derived from ClientBase<T> will internally call the Close() method of the class and this method might in turn throw exceptions. So wrapping a proxy based on ClientBase<T> in a Using() is not always safe.

So to reiterate the question(s):

  • How should I clean up my web service proxy after using it when the proxy is based on SoapHttpClientProtocol?
  • How should I clean up my web service proxy after using it when the proxy is based on ClientBase<T>?
Gough answered 3/5, 2013 at 9:42 Comment(0)
G
14

Based on my best efforts to find the answer to this question, I'd say that for SoapHttpClientProtocol based proxies (regular .asmx web service proxies) the correct way is to simly wrap it in using():

using(var testProxy = new TestAsmxServiceProxy())
{
    var response = testProxy.CallTest("foo");

    // process the reponse
}

For proxies based on ClientBase<T> (WCF proxies) the answer is that it should not be wrapped in a using() statement. Instead the following pattern should be used (msdn reference):

var client = new TestWcfServiceProxy();
try
{
    var response = client.CallTest("foo");
    client.Close();

    // process the response
}
catch (CommunicationException e)
{
    ...
    client.Abort();
}
catch (TimeoutException e)
{
    ...
    client.Abort();
}
catch (Exception e)
{
    ...
    client.Abort();
    throw;
}
Gough answered 31/5, 2013 at 10:25 Comment(1)
I'm not sure about the first part of this. Dispose is implemented by Component, but Abort is implemented by WebClientProtocol. Looking at the code it appears that Dispose couldn't know about the request. msdn.microsoft.com/en-us/library/ff647786.aspx seems to back that up (under "Abort Connections for ASP.NET Pages That Timeout Before a Web Services Call Completes"). For WCF, see #574372Excurrent

© 2022 - 2024 — McMap. All rights reserved.