tags:

views:

271

answers:

2

So as to enable aysc callbacks to the clients, I need to add the Begin/End methods to the interface that is defined as the CallbackContract on my service. (I am using a sheared contract assembly, rather than generating proxy classes)

[ServiceContract(CallbackContract=typeof(IClient)]
interface IEngineManager

As the first step I have just copied the IClient interface from the shared interface assembly into a local name space, without making any other changes. I would expect that as the interface is logically the same as what is in the contract, WCF will allow it to be used. However WCF does not like it for some reason, why?

[ServiceContract]
public interface IClient
{
  [OperationContract(Action = "ReceiveMessage", 
     ReplyAction = "ReceiveMessageResponse")]
  void ReceiveMessage(SimMessage message);
}

//....
// this give the InvalidCastException
var client = OperationContext.Current.GetCallbackChannel<MyNameSpace.IClient>();

However if I just use the original IClient interface from the shared contract assembly, it all works!

+1  A: 

As DxCK siad the type that is passed to OperationContext.Current.GetCallbackChannel<T>() must be exactly the same type as you specified in the [ServiceContract] attribute on the interface that the service implements.

However I need to use a different interface for the callbacks so I can add the Begin/End methods needed to support aysc callbacks.

So firstly my new callback interface.

[ServiceContract]
public interface IClientWithAsyncMethods : IClient
{
  [OperationContract(
    AsyncPattern = true, 
    Action = "ReceiveMessage", 
    ReplyAction = "ReceiveMessageResponse")]
  IAsyncResult BeginReceiveMessage(SimMessage message, 
    AsyncCallback callback, object asyncState);

  void EndReceiveMessage(IAsyncResult asyncResult);
}

Then need to define a new interface for my service to implment:

[ServiceContract(CallbackContract = typeof(IClientWithAsyncMethods))]
public interface IEngineManagerWithAsyncCallbacks : IEngineManager
{
}

The only change to to refare to the new callback interface as the CallbackContract, this is OK as IClientWithAsyncMethods is a subtype of IClient.

Then the last step is to change the serve implementation to use to the service interface:

  • Change the interface type the service implements
  • Pass the new interface into ServiceHost.AddServiceEndpoint() (and/or edit the WCF config files)
  • Use IClientWithAsyncMethods in the call to OperationContext.Current.GetCallbackChannel<IClientWithAsyncMethods>()

The rest is just calling the aysc method in the normal way.

Ian Ringrose
+2  A: 

When you do GetCallbackChannel you should specify exactly the same type as you specfied in the [ServiceContract] attribute, its strongly typed.

Even if A.IClient and B.IClient have exactly the same code with only namespace changed, those are completely different types from .NET's view.

DxCK