After much hair pulling I have found a solution to this problem, I am not particularly happy with it but it is a solution none the less. After doing some further debugging it seems that when the A to B request is made the .NET Framework pushes this into the incorrect channel (i.e. the Client to A) as this channel has different sinks, when B receives the data it is unable to process it. Interestingly if I unregistered the Client to A channel the A to B call would work, obviously this isn't a solution as this then breaks all Client to A comms. At first it seemed that the solution was obvious, make sure that the correct channel is used. After much googling I have been unable to find a method of doing this. I did however find alot of people with the same problem ;) So the solution... The server B remoting framework has a client library which is installed on A. This library contains all the methods that B exposes across remoting. The solution was to create a wrapper around this client library, on instantiation the wrapper creates a new AppDomain and loads the client library into it. I then use a marhsalled transparent proxy object across to call the client library. Doing this means that the new AppDomain on has a single TcpChannel registered and therefore the selection issue doesn't exist. As always with these things there was a gotcha, which is if you leave the AppDomain unused for more than 5 minutes (default) the lease expires and the proxy fails. This can be fixed by, in the client library, overriding "InitializeLifetimeService" and returning null. So, wrapper code:
public sealed class ClientLibraryWrapper
{
AppDomain clientDomain;
ServerB.Client.EntryPoint client;
public ClientLibraryWrapper
{
this.clientDomain = AppDomain.CreateDomain("ServerBClientDomain");
Assembly clientAssembly = Assembly.LoadFile(Environment.CurrentDirectory + @"\\ServerB.Client.dll");
this.clientDomain.Load(clientAssembly.FullName);
Object obj = mhsClientDomain.CreateInstanceAndUnwrap(clientAssembly.FullName, "ServerB.Client.EntryPoint");
this.client = (ServerB.Client.EntryPoint)obj;
}
public int ServerBMethod()
{
this.client.ServerBMethod();
}
}
Client library code:
public sealed class EntryPoint : MarshalByRefObject
{
public override object InitializeLifetimeService()
{
return null;
}
public int ServerBMethod()
{
return 1;
}
}