I have this problem. I have two WCF services - ServiceA
and ServiceB
. Both services are host in different windows services and communicate via net.tcp. Client access Service A
. In Service A
I access Service B
. Problem what I got is that I want to communication be duplex.
That is I want client to call method TestA
in ServiceA
. This method would call method TestB
in ServiceB
. Method TestB
would make some long duration action and then raises callback back to ServiceA
that would raises callback to client. Methods TestA
and TestB
are one way contracts.
I can get to the point in which ServiceA
raises callback back to client. Then it crashes on InvalidCastException trying to get callback channel in operation context.
IServiceACallback Callback
{
get
{
return OperationContext.Current.GetCallbackChannel<IServiceACallback>();
}
}
Is it because I am in a different thread and operation context is just simply not complete? Because I can raise callback back to client when I am not doing it from another callback from ServiceB
. Can I solve it with some service attributes maybe? Or is there some communication pattern that I can use?
Ok, I figure it out.
By raising callback from ServiceB
to ServiceA
I was in different OperationContext. This context was on entirely different thread so got no connection with the Client
but instead got part of OperationContext from ServiceB
.
I added new member to CallbackHandler of ServiceA
that points to OperationContext. To this I pass current context during creation of ServiceB
using DuplexChannelfactory
. This context is the correct one and can be used to raises callbacks back to Client
. I hope that code makes it understandable.
Creation of ServiceB
in ServiceA
:
InstanceContext context = new InstanceContext(new CallbackHandler(OperationContext.Current));
ChannelFactory<IService> factory = new DuplexChannelFactory<IServiceB>(context, binding, address);
IServiceB service = factory.CreateChannel();
CallbackHandler of ServiceA
:
public class CallbackHandler : IServiceBCallback
{
OperationContext _context;
public CallbackHandler(OperationContext context)
{
_context = context;
}
public void TestProgress(string msg)
{
IServiceACallback callback = _context.GetCallbackChannel<IServiceACallback>();
callback.TestProgress(msg);
}
}