Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

A Better Way for a Client to Work with WCF Services

5.00/5 (2 votes)
8 Nov 2010CPOL3 min read 50.6K   903  
A component which allows to work with WCF services in a robust way
ClientComponent.png

Introduction

In my opinion, Microsoft failed with the implementation of the generic ClientBase implementation that is used for connecting with services. The channel contained within the client base implementation will become invalid when a problem occurs during the communication with the service.

The downside is that this channel cannot be revived so that it can be reused. The only solution is to dispose the current instance and to recreate a new one. This will put a strain on the developers since they need to implement the code for handling the invalid channel and for recreating the actual client proxy.

As one can imagine, this is not efficient and can cause problems since each client proxy needs to be implemented in their own way. Some functionality can be copied and pasted, but this will be error prone.

Other Solutions

I did some browsing to see if others ran into the same problems. The only interesting solution I found was at http://www.acorns.com.au/blog/?p=113 and shows a dynamic proxy which is generated at runtime. This was almost exactly what I had been looking for. The solution however was too complex for my taste, so I started on my own version while reusing certain ideas and the intermediate language generation.

The solution to the problem is to encapsulate the actual client proxy, which is based on the ClientBase, in a specific class which will contain the functionality to recreate the proxy in case of problems. The problem however is that the calls present on the service interface need to be extended with a way to detect these problems. To be able to handle this in a generic way, we need to generate this functionality at runtime to prevent that we still need actions to keep the implementation up to date. This can be done by creating a temporary assembly which will contain the implementation for the specific implementation of the interface by generating intermediate language.

So a generic ProxyClassBuilder is available which will generate a type that contains the methods which will handle the calls to the service implementation. Each method will contain functionality for catching exceptions and for handling them accordingly.

Code Generation

I will explain shortly what happens when the following service contract is being used:

C#
[ServiceContract]
public interface ITestService
{
     [OperationContract]
     void DummyCall();
}

The following will trigger the creation of the specific client proxy which includes the method and the implementation that will handle any exceptions that occur.

C#
clientProxy = ClientProxy<itestservice />.GetInstance("identifier", binding, endpointAddress);

The client proxy that is returned is derived from the ClientProxy class and will contain the following implementation:

C#
public class TestService : ClientProxy<itestservice />, ITestService
{
    // Methods
    public TestService(Binding binding1, EndpointAddress address1) : 
        base(binding1, address1)
    {
    }

    public void DummyCall()
    {
        try
        {
            base.Channel.DummyCall();
        }
        catch (Exception exception)
        {
            this.HandleException(exception);
        }
    }
}

It will pass the method call onto the enclosed channel which will eventually call the service. Any exceptions are caught and passed onto the HandleException method which resides in the base class.

Classes Involved

The generic ClientProxy is the entry point and the one that is to be used by the consumer of the service. It has an abstract method GetInstance which is used to get an instance of the generated class. This generated class is completely built by the ProxyClassBuilder. For performance issues, the ClientProxy will contain a cache with already generated client proxies. This ensures that the communication with a certain service within the same client is done via one instance of the proxy.

The generic ProxyClassBuilder is responsible for the generation of a temporary type. This type is cached internally to prevent that it needs to be generated more than once.

The generic InternalClientProxy is the actual proxy that talks with the service. This one is recreated when the connection with the server is somehow severed.

The Enclosed Solution

The enclosed solution contains 3 projects:

  • The test application with a simple user interface which supports that starting/stopping of the service, calling the methods on the client proxy and logging some information regarding the process.
  • The test service itself, it contains both the interface and the implementation. This is not the way to go, but hey it is just an example.
  • The actual implementation for the dynamic client proxy. This contains the interesting part with the generation of the client proxy by using the intermediate language.

History

  • 8 Nov 2010 - First version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)