views:

3706

answers:

3

How can I set the HTTP proxy programmatically, on a WCF client, without using the default proxy?

Proxies, proxies, proxies.

According to the WCF model of development, I generate client-side "proxy" classes by running svcutil.exe on the WSDL for the service. (This also produces a client-side config file).

In my code I new-up an instance of that class and I can connect to the service. Very nice.

var svcProxy = new MyWebService();
svcProxy.GetInformation(request);

We call this thing a proxy class, but there is another proxy - the http proxy. This service is using wsHttpBinding basicHttpBinding, so it is going over http. Now, suppose I want to connect the client to the web service over a http proxy (modeled by a System.Net.WebProxy in the .NET BCL). I know from my extensive, delightful experience reading .NET and WCF documentation, that the WCF runtime, if not instructed otherwise, will use the default system proxy when communicating over http/https.

I can set that from the command line in WinXP / 2003 with ProxyCfg.exe as described here, and in later versions of Windows with netsh.exe as described here.

I can also specify the default web proxy for use within the application by setting the System.Net.WebRequest.DefaultWebProxy property.

But suppose I want to connect over a proxy that is different than the system-wide proxy? For instance maybe there is no system-wide proxy but I need to use one for the web service in particular. Or maybe there is a system-wide proxy but I need to use a different one, for the web service. And in fact maybe there are multiple web service clients, and each one should get a different proxy.

How can the proxy be set per-binding?

In the ASMX model, I could do this:

var svcProxy = new MyWebService();
svcProxy.Proxy = new System.Net.WebProxy("http://proxyserver:1234", true);
svcProxy.GetInformation(request);

But this is not possible with WCF; the WCF-generated client-side proxy classes do not expose a Proxy property. How do I set the http proxy, per client-side proxy, and how do I set authentication on the http proxy as well?

Related:
- how-to-set-proxy-with-credentials-to-generated-wcf-client

+2  A: 

The proxy settings are part of the binding configuration. For example, look at the ProxyAddress property of the BasicHTTPBinding and WSHttpBinding classes/configuration elements.

Looks like you're leaving your endpoint configuration in the app.config file, in which case you should be able to set the address there.

tomasr
+4  A: 

It makes sense that there is no Proxy property on the WCF proxy, because not all WCF proxies use HTTP for communication. After further review, I found that it is possible to set the proxy in WCF programmatically, if the WCF proxy uses an HTTP binding. I am documenting it here in case someone else needs it. To set the HTTP Proxy in code for a WCF client, do this:

    // instantiate a proxy for the service
    var svc= new ServiceClient();
    // get the HTTP binding
    var b = svc.Endpoint.Binding as System.ServiceModel.BasicHttpBinding;
    b.ProxyAddress = new Uri("http://127.0.0.1:8888");
    b.BypassProxyOnLocal = false;
    b.UseDefaultWebProxy = false;

And to set the endpoint address - where to reach the server - in code, you would do something like this:

    var e = svc.Endpoint;
    e.Address = new System.ServiceModel.EndpointAddress("http://remoteserver:5555/WcfXmlElement");
Cheeso
+3  A: 

I have had a similar problem, but I also needed to use a username and password for the proxy that differ from the username and password used to access the service.

I tried building it up through a UriBuilder, which would output the proxy address as "http://username:password@myproxyserver/". Unfortunately, the particular proxy I was using didn't work with this technique.

What I found after extensive Googling, is that you can change the proxy through WebRequest.DefaultProxy (static property).

For example:

WebProxy proxy = new WebProxy("http://myproxyserver",true);
proxy.Credentials = new NetworkCredential("username", "password");
WebRequest.DefaultWebProxy = proxy;
Martin Clarke
Yes. Of course if you do this you must set UseDefaultWebProxy=true. I think there is also a way to do this on a per-client binding basis. If b is a System.ServiceModel.BasicHttpBinding, You would need to set b.Security.Transport.ProxyCredentialType to whatever your proxy requires. The enum is HttpProxyCredentialType and the possible values are {None, Basic, Digest, Ntlm, Windows}. See this post for a hint:http://kennyw.com/indigo/106
Cheeso
Thanks for the link Cheeso. I'll give it a whirl when I'm back in the office on Moday :)
Martin Clarke