I've been doing a lot of WCF development lately (love it) and ran into a bit of a stumbling block. The proxy client generated by Visual Studio 2008 Beta 2 doesn't handle fault conditions and dispose well. I have to admit, I haven't used WCF in Visual Studio 2005. If you're impatient here's the project (Visual Studio 2008 Beta 2 project): wcfwrapper.zip The situation unfolds:
         The Problem - Dispose Isn't Safe!
   
- Create a WCF service.[ServiceContract] 
 public interface IGoodBadService
 {
 [OperationContract]
 void Good();
 [OperationContract]
 void Bad();
 }
- Add a service reference to your service in another project.
- Create a service client and use it, with a "using" block (it is IDisposable, afterall).                try 
 {
 using (GoodBadServiceClient c =
 new GoodBadServiceClient())
 {
 c.Bad();
 }
 }
 catch (Exception ex)
 {
 Console.WriteLine(ex.Message);
 }
- A call to your service, for whatever reason, throws an exception.public class GoodBadService 
 : IGoodBadService
 {
 public void Good()
 {
 throw new Exception("GOOD!");
 }
 public void Bad()
 {
 throw new Exception("BAD!");
 }
 }
- You get a cryptic System.ServiceModel.CommunicationObjectFaultedException instead of the real exception when using calls Dispose() on your proxy client. It reads: The communication object, System.ServiceModel.Channels.ServiceChannel, cannot be used for communication because it is in the Faulted state.
         The Solution - A Simple Generic Wrapper
public class ServiceProxy<TClient>
: IDisposable
where TClient : ICommunicationObject
{
public ServiceProxy(TClient client)
{
Client = client;
}
public TClient Client { get; private set; }
public void Dispose()
{
if (null != Client &&
Client.State != CommunicationState.Closed &&
Client.State != CommunicationState.Faulted)
{
Client.Close();
}
}
}
Using the wrapper is pretty straightforward, but a tad more cryptic than just using the client directly. Some of this can be avoided with a generic factory.
         So, here's how you use it:
tryRun the project and check out the results. The wrapper gives you the actual exception, whereas "using" the client directly causes the CommunicationObjectFaultedException. Here's the project (Visual Studio 2008 Beta 2 project): wcfwrapper.zip
{
using (ServiceProxy<GoodBadServiceClient> c
= new ServiceProxy<GoodBadServiceClient>(
new GoodBadServiceClient()))
{
c.Client.Good();
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
 
No comments:
Post a Comment