Question

I have a duplex channel that uses callbacks to provide updates as part of a subscription to some data (see below for interfaces). Occasionally that data is unavailable and when it is the server needs to shut down its subscription and let the client open a new one, so I want to notify the client that it needs to do so.

  • What is the correct way to do so?
  • Is it possible to pass back a FaultException via the IUpdate interface? It seems that the throw new FaultException(...); syntax is specific to request-response.
  • Do I need return a custom fault somehow?
  • Do I just have to add a new OnError function or similar that explicitly forces the client to reconnect?

.

[ServiceContract(Namespace = "http://tempura.org/ISubscribe", Name = "ISubscribe", ConfigurationName = "Subscribe", CallbackContract = typeof(IUpdate))]
interface ISubscribe
{
    [OperationContract]
    long Subscribe();

    [OperationContract(IsOneWay = true)]
    void Unsubscribe(long index);
}

[ServiceContract(Namespace = "http://tempura.org/ISubscribe")]
public interface IUpdate
{
    [OperationContract(IsOneWay = true)]
    void OnUpdate(string update);
}
Was it helpful?

Solution

Using what you have there, sending (string update) between the host and client, you can't throw and catch the error. From my experience, you'd either need to:

a) add another function, as you suggest "add a new OnError function ... ", containing an error flag and string for the message, or

b) change the String in OnUpdate function to an object containing your return string, but also a bError flag, a string for an error message or perhaps an Exception object.

Then, as the client is looping and listening for an inbound message, check the new function or object for your error conditions.

That's what I'm doing ...

OTHER TIPS

First of all, I'd consider about @Aron idea about not using duplex if you are not required.

If you do, I'd try the following steps:

  1. When you are establish the connection from client - subscribe to channel Faulted event:

    ((IClientChannel)my_ISubscribe_channel).Faulted += Server_Channel_Faulted;
    
  2. Implement Server_Channel_Faulted method to re-connect to server. Be sure on the server to update your subscription.

Updated:

  1. If server should be initiator of the re-connection, you can add method on client side callback, that will enforce re-connect to server.

EDITED

A duplex channel between A and B is a shortcut for A as client to B, and B as client to A, effectively giving you 2-way communication between A and B.

If in your case, B needs to notify A that its subscription is lost, B can simply send a request to A. FaultExceptions are serializable, so if A really needs to know what went wrong in B, B can simply pass a FaultException in the message.

Your callback contract would then become:

[ServiceContract(Namespace = "http://tempura.org/ISubscribe")]
public interface IUpdate
{
    [OperationContract(IsOneWay = true)]
    void OnUpdate(string update);

    [OperationContract(IsOneWay = true)]
    void OnSubscriptionLost(FaultException exception);
}

But I agree with @Aron that this is a poor implementation of pubsub.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top