WCF Dynamic ClientBase Proxy part two

12:10 pm .Net, Readify, Tools, WCF

A while ago I wrote a Reusable Client Proxy that allows you to reuse the ClientBase proxy even if it faults without the developer having to take care of the complicated lifetime management and make sure it is closing the proxy if it gets into a faulted state.

After several months of using this proxy and some good feedback I started to write a new version of this proxy and do several small changes:

  • Fixed bug that proxy was not correctly generated if there were multiple levels of inheritance on the contract interface.
  • Added an IClientBase interface that gets implemented automatically that gives access from outside to the ClientBase specific properties (ClientCredentials, EndPoint, InnerChannel and State)
  • Added an event on this interface: ProxyCreated that gets triggerd after a new instance of the proxy was created (e.g. due to a fault) so you can reinitialize the proxy, set the ClientCredentials or any other operations you want to do with the IClientBase.
  • Added support to automatically unwrap Exceptions out of FaultExceptions.
  • The assembly is now signed by default so you can start using it immediatelly.

Implementation details:

FIX: Proxy was not correctly generated for multi-inheritance interfaces

Trying to create a proxy on the IService2 was failing as the code was not generating the MyOperation1 method:

[ServiceContract()]
public interface IService1
{
    [OperationContract]
    string MyOperation1(string arg1, int arg2);
}
[ServiceContract()]
public interface IService2 : IService1
{
    [OperationContract]
    void MyOperation2(string value);
}

Added the IClientBase interface to the generated proxies

A new IClientBase interface was added and all the relevant properties and methods from the real ClientBase<T> class are now exposed.

The interface is only exposed on the objects returned by the GetReusableInstance method.

A new event was also added on the interface: ProxyCreated that is fired every time a new proxy had to be created due to the old one failing.

The event can be used to apply custom ClientCredentials or behaviours.

public delegate void ProxyCreatedHandler(IClientBase proxy);

/// <summary>
/// Interface to expose the inner ClientBase properties hidden by the Proxy
/// </summary>
public interface IClientBase
{
    /// <summary>
    /// Fired when a new proxy is created.
    /// In here you can initialize the Credentials and EndPoints.
    /// </summary>
    event ProxyCreatedHandler ProxyCreated;

    /// <summary>
    /// Gets the client credentials used to call an operation.
    /// Returns a System.ServiceModel.Description.ClientCredentials that represents
    /// the proof of identity presented by the client.
    /// </summary>
    ClientCredentials ClientCredentials { get; }

    /// <summary>
    /// Gets the target endpoint for the service to which the WCF client can connect.
    /// </summary>
    ServiceEndpoint Endpoint { get; }

    /// <summary>
    /// Gets the underlying System.ServiceModel.IClientChannel implementation.
    /// </summary>
    /// <value>The client channel for the WCF client object.</value>
    IClientChannel InnerChannel { get; }

    /// <summary>
    /// Gets the current state of the System.ServiceModel.ClientBase<TChannel> object.
    /// </summary>
    CommunicationState State { get; }

    /// <summary>
    /// Causes the System.ServiceModel.ClientBase<TChannel> object to transition
    //     immediately from its current state into the closed state.
    /// </summary>
    void Abort();

    /// <summary>
    /// Causes the System.ServiceModel.ClientBase<TChannel> object to transition
    //     from its current state into the closed state.
    /// </summary>
    void Close();

    /// <summary>
    /// Causes the System.ServiceModel.ClientBase<TChannel> object to transition
    //     from the created state into the opened state.
    /// </summary>
    void Open();
}

Having the new ProxyCreated event allows a much cleaner type of code to be implemented.

For example if you know you need custom username/password authorization you can subscribe to the event:

IService1 service = WCFClientProxy<IService1>.GetReusableInstance("Service1");
(service as IClientBase).ProxyCreated += new ProxyCreatedHandler(Program_ProxyCreated);

Then handle the event to do the custom authorization:

static void Program_ProxyCreated(IClientBase proxy)
{
    proxy.ClientCredentials.UserName.UserName = "myUser";
    proxy.ClientCredentials.UserName.Password = "myPassword";
}

Other changes

  • Renamed GetWrappedInstance to GetReusableInstance.
  • Dropped the references to the Enterprise Library just in case you don’t use them so the assembly has no external references.
  • Set the version number to 1.2.0.

Update: You can find the Readify.WCF.DynamicClientProxy 1.2 including the source code here.

23 Responses

  1. RJ Says:

    Hi Corneliu,
    First, very nice work you’ve done here!

    Last time you released this dynamic clientbase proxy with the source code. Is there a possiblity that you can send me the code base? That would save me quite some work :)
    Thank you!

  2. Corneliu Says:

    RJ,
    I’ve updated the link to include the source code as well.
    Enjoy,
    Corneliu.

  3. Rory Primrose Says:

    Hi Corneliu,

    I implemented something similar, but I used RealProxy under the covers. For performance, I implemented a method cache of method handles rather than constantly resolving a MethodBase from a string name and set of parameters.

  4. Corneliu Says:

    Rory,
    Once you create the first proxy for a specific interface I cache the proxy type so there is no need to cache the method handle anymore as all the calls are emited and there is no reflection used at all once you have the proxy instance.
    Corneliu.

  5. reno Says:

    How do we dispose of the client proxy? After a while it runs out of connections. I think that’s the reason ClientBase implemented IDisposable to encourage people to dispose of the client and not keep it around for a long time. Reusing the same client around in one method call or method call chain is fine, but we should drop the connection as soon as we’re done.

  6. reno Says:

    Nevermind ignore my last comment — I figured it out. I’m stupid :)

  7. jeff Says:

    Thanks for the great source. I’m particularly interested in how you cache subsequent proxy generation. Looked through the code and don’t see it. Could you help me out to understand it?

  8. jeff Says:

    Disregard the previous comment.

  9. jeff Says:

    How does one actually use the code? Any samples? I see the caching and I see the classes but how you actuall use it? Please help out.

  10. Corneliu Says:

    Jeff,
    Part one (http://www.acorns.com.au/blog/?p=86) had example how to use the client proxy.
    Basically all you do have to do is:
    IService1 service = WCFClientProxy.GetWrappedInstance(“Service1“);
    This will get a WCF instance to your service all wrapped and ready to use.
    The code does not cache the proxy itself. It will cache the class type used to generate the proxy so next time you ask for it, it instantiates it and is ready to go.
    Regards,
    Corneliu.

  11. Ben Says:

    Hi Corneliu,
    Have you already think about generating asynchronous operations, if they are in the interface for example with a custom attribute like this :
    void DoWork();
    [AsyncMethod(AsyncType.Begin, "DoWork")]
    void BeginDoWork();
    [AsyncMethod(AsyncType.End, "DoWork")]
    void EndDoWork();
    Your Dynamic client proxy seems to be very good, and is exactly what I was looking for but loosing asynchronous operations can be a problem in some cases I think.
    Ben.

  12. Corneliu Says:

    Ben,
    That sounds interesting. I’ll look into that see how complex it is to build.
    Regards,
    Corneliu.

  13. Garth Says:

    thank you been looking for a username/pwd sample all over the place

  14. Darrell Says:

    Great code, thanks for posting it.

    I have a quick question. If I want to set my endpoint and binding programmatically, how would I do that?

    Thanks,
    Darrell

  15. Pedro Says:

    Hi,
    Thanks for this very nice code that I’m using in one app.
    For any reason you got a CommunicationObjectAbortedException after a inactivity period?
    I’m using net.tcp hosted on a windows service. Everything works fine until some inactivity. Calling the same operation the client throws the exception “An existing connection was forcibly closed by the remote host
    “.
    I put some wcf logging on the server and the exception is “The communication object, System.ServiceModel.Channels.ServerSessionPreambleConnectionReader+ServerFramingDuplexSessionChannel, cannot be used for communication because it has been Aborted.”
    Could this be related with the dynamic proxy?
    Thanks.

  16. George Says:

    Hi Corneliu

    Firstly awesome code.

    Did you have a chance to look at asynchronous operations?

    I’m using WPG and Silverlight and asynchronous is a must.

    Thanks
    George

  17. George Says:

    WPG?? I meant WPF.

  18. Gary Says:

    Thanks for sharing this Corneliu – saved me a ton of time.

  19. Nate Says:

    This is extremely useful and well done, thank you. One issue: When I use GetReusableFaultUnwrappingInstance and an exception occurs, the outer exception is still thrown and not the inner exception. (In other words the actual fault is not unwrapped.) Could you look at that again to see if there is some bug?

  20. William Says:

    Hi Corneliu,

    After making 10 calls, my service starts to freeze, and have to wait 10 mins time-out before i can use it again making more calls.

    How can I increase the max connections, and also closing the proxy when its finish?

    thanks
    Will

  21. Corneliu Says:

    Nate,
    The framework should only do that if the inner fault is NOT an exception. If the inner fault is an exception it should be properly raised. Can you please send me a sample where you have the issue.

    William,
    Like with all WCF connections you need to dispose them.
    Easiest is to cast the received interface to IClientBase and do a using for example:
    IMyService service = WCFClientProxy.GetInstance(”MyService”);
    using( (IClientBase)service )
    {
    …..
    }
    This will properly close the connection once you exit the using statement.
    Look at the IClientBase interface for more details.
    Corneliu.

  22. AroglDarthu Says:

    Excellent article! A few questions arose while digging through the sources though:
    There seems to be a mismatch between WCFClientProxy.RegisterEndpoint and WCFClientProxy.GetRegisteredInstance. The first builds the type with the non-reusable’ builder. The second forwards to WCFClientProxy.GetReusableInstance and results in a different type being build. Perhaps RegisterEndpoint needs an enum to indicate which builder to use?
    In the WCFAbstractReusableClientProxy.AssureProxy method a call is placed to WCFClientProxy.GetInstance… Does that mean the ‘reusability’ is limited to only once? I guess it should read GetReusableInstance here ;-)

  23. parallelthinking » Blog Archive » WCF Dynamic (ClientBase) Proxy part three: Connection Pooling and Automatic Disposing Says:

    [...] Automatic Disposing February 17, 2009 2:14 pm Corneliu .Net, WCF, WCF Dynamic Proxy A while ago I published a small and neat Dynamic Proxy that could be used to automatically create for you implementation of the (WCF) ClientBase<T> [...]

Leave a Comment

Your comment

You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Please note: Comment moderation is enabled and may delay your comment. There is no need to resubmit your comment.