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