Cook Computing

WebProxy and localhost

January 17, 2003 Written by Charles Cook

I wasted some time last night trying to use the .NET WebProxy class to route XML-RPC calls through ProxyTrace. I'd been playing around with some code LLoyd Dupont sent me which configured an instance of HttpChannel for XML-RPC programmatically without using a config file (the example in the XML-RPC.NET FAQ uses a config file):


ListDictionary prop = new ListDictionary();
prop.Add("port", 1971);
HttpChannel channel = new HttpChannel(prop, null,
  new XmlRpcServerFormatterSinkProvider(null, null));
ChannelServices.RegisterChannel(channel);
RemotingConfiguration.RegisterWellKnownServiceType(
  typeof(Server), "myApp/anURI", 
  WellKnownObjectMode.Singleton);

I thought it would make debugging very easy if the client and server were in the same executable, using ProxyTrace so you could watch the XML-RPC requests and responses. However I couldn't get the WebProxy instance to work. It was being ignored. I tried placing the server class in a separate AppDomain before discovering that WebProxy wouldn't work for any clients connecting to servers running on the same machine. Google pointed me to the the answer on Mindreef.blog:

... the System.Net.WebProxy class that comes with the .NET Framework will not proxy HTTP requests to localhost

The solution is to use the machine's hostname or IP address when setting the Url property of XmlRpcClientProtocol and not localhost.

The moral: when you have a problem, never waste time trying to fix it before searching for the answer on Google.

The full code for the combined XML-RPC client and server is below. By the way, an XML-RPC version of SOAPscope would make a nice project for someone.


using System;
using System.Net;
using System.Collections.Specialized;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Http;
using System.Runtime.Remoting;
using CookComputing.XmlRpc;
 
interface IHello
{
  [XmlRpcMethod("hello.getGreeting")]
  string getGreeting(string name); 
}
 
public class Server : MarshalByRefObject, IHello
{
  public string getGreeting(string name)
  {
    return "Hello " + name;
  }
 
  public static void Run() 
  { 
    ListDictionary prop = new ListDictionary();
    prop.Add("port", 1971);
    HttpChannel channel = new HttpChannel(prop, null,
      new XmlRpcServerFormatterSinkProvider(null, null));
    ChannelServices.RegisterChannel(channel);
    RemotingConfiguration.RegisterWellKnownServiceType(
      typeof(Server), "myApp/anURI", 
      WellKnownObjectMode.Singleton);
  } 
}
 
public class Client
{
  public static void Run()
  {
    IHello hello = (IHello)XmlRpcProxyGen.Create(typeof(IHello));
    (hello as XmlRpcClientProtocol).Url 
      = "http://netherton:1971/myApp/anURI";
    (hello as XmlRpcClientProtocol).Proxy 
      = new WebProxy("http://localhost:8080");
    while (true)
    {
      Console.Write("Enter name: ");
      string s = Console.ReadLine();
      if (s == "")
        break;
      Console.WriteLine(hello.getGreeting(s)); 
    }
  }
}
 
public class _
{
  static void Main()
  {
    Server.Run();
    Client.Run();
  }
}