I'd really appreciate help on the following. I am working with remoting, and am having a problem supporting both an http channel with a binary formatter and an http channel with a soap formatter in the same client application instance. I setup a simple test below. I have a remoting server instance listening on one port for http binary, and a second port for http SOAP, both serving the same type (InventoryService).
If I run the client with only the http channel with soap formatter, or the http channel with only the binary formatter, the calls complete correctly (per the conditional #defines at top). If I run a test executing two client applications concurrently, one with an http channel/soap formatter and the second with the http channel/binary formatter, everything works fine (i.e., the server handles it). However if I run both http/soap and http/binary channels within the same instance, I get an exception thrown. It looks like the formatter isn't deserializing properly: Unhandled Exception: System.Runtime.Remoting.RemotingException: System.ArgumentNullException: No message was deserialized prior to calling the DispatchChannelSink. Parameter name: requestMsg at System.Runtime.Remoting.Channels.DispatchChannelSink.ProcessMessage (IServerChannelSinkStack sinkStack, IMessage requestMsg, ITransportHeaders requestHeaders, Stream requestStream, IMessage& responseMsg, ITransportHeaders& responseHeaders, Stream& responseStream) 1) Is it legitimate to run both http binary and soap channels within the same client instance? As far as I can tell, this should not pose a problem. 2) If it is legitimate, then shouldn't the remoting runtime properly select the channel based upon the server the correct http channel to use based upon the protocol supported by the server? I don't see a way to force the correct channel to be selected. I can provide full source to anyone interested. Client Code as follows: #define TEST_HTTP_BINARY #undef TEST_HTTP using System; using System.Runtime.Remoting; using System.Runtime.Remoting.Channels.Tcp; using System.Runtime.Remoting.Channels.Http; using System.Runtime.Serialization.Formatters.Binary; using System.Runtime.Remoting.Messaging; using System.Runtime.Remoting.Channels; using System.Threading; using System.Collections; namespace RemotingSample { class TestClient { static ManualResetEvent ev = new ManualResetEvent(false); [STAThread] static void Main(string[] args) { Hashtable settings = new Hashtable(); settings.Add("name", "tcp"); settings.Add("port", "0"); TcpChannel tcp = new TcpChannel(settings, null, null); ChannelServices.RegisterChannel(tcp); TestClient trc = new TestClient(); #if (TEST_HTTP) settings.Clear(); settings.Add("name", "http"); settings.Add("port", "0"); HttpChannel http = new HttpChannel(settings, new SoapClientFormatterSinkProvider(), new SoapServerFormatterSinkProvider()); ChannelServices.RegisterChannel(http); #endif #if (TEST_HTTP_BINARY) settings.Clear(); settings.Add("name", "httpbin"); settings.Add("port", "0"); HttpChannel httpbin = new HttpChannel(settings, new BinaryClientFormatterSinkProvider(), new BinaryServerFormatterSinkProvider ()); ChannelServices.RegisterChannel(httpbin); #endif // gauge relative speed of different protocols and hosting mechanisms // T1: tcp, binary Thread t1 = new Thread(new ThreadStart(trc.RunTest)); t1.Name = "tcp://localhost:8089/Inventory"; t1.Start(); ev.WaitOne(); ev.Reset(); #if (TEST_HTTP) // T2: http, soap Thread t2 = new Thread(new ThreadStart(trc.RunTest)); t2.Name = "http://localhost:8090/Inventory"; t2.Start(); ev.WaitOne(); ev.Reset(); #endif #if (TEST_HTTP_BINARY) // T3: http, binary Thread t3 = new Thread(new ThreadStart(trc.RunTest)); t3.Name = "http://localhost:8091/Inventory"; t3.Start(); ev.WaitOne(); ev.Reset(); // T4: http, binary, iis Thread t4 = new Thread(new ThreadStart(trc.RunTest)); t4.Name = "http://localhost:80/InventoryService/Inventory.rem"; t4.Start(); ev.WaitOne(); #endif } public void RunTest() { try { string url = Thread.CurrentThread.Name; Inventory.InventoryService invsvc = (Inventory.InventoryService)Activator.GetObject(typeof (Inventory.InventoryService), url); long start = DateTime.Now.Ticks; int i = 0; for(i = 0; i < 1000; i++) { invsvc.CheckInventory("132456"); } long elapsed = DateTime.Now.Ticks - start; elapsed /= 10000; // Get into millsecs Console.WriteLine(elapsed + "ms elapsed for " + i + " iterations(" + ((float) elapsed)/i + "ms per call, in call: " + invsvc.ReportAverageTime() + ") on url: " + url); } finally { ev.Set(); } } } } You can read messages from the Advanced DOTNET archive, unsubscribe from Advanced DOTNET, or subscribe to other DevelopMentor lists at http://discuss.develop.com.