48

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

Community
  • 1
  • 1
Cheeso
  • 180,104
  • 92
  • 446
  • 681

5 Answers5

59

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");
Ruben Bartelink
  • 55,135
  • 22
  • 172
  • 222
Cheeso
  • 180,104
  • 92
  • 446
  • 681
27

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
  • 13,413
  • 3
  • 35
  • 30
22

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
  • 5,459
  • 7
  • 35
  • 57
  • 6
    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 Jun 26 '09 at 18:18
  • Thanks for the link Cheeso. I'll give it a whirl when I'm back in the office on Moday :) – Martin Clarke Jun 26 '09 at 19:48
  • This is what I want, but don't want to set credentails programmatically or in some config file. My client app needs to automatically detect proxy address and port, user creds (and domain if required). Right now is does partially work the way I want if proxy does not require authentication. Proxy address is detected from windows network setting automatically. How can I get credentials to work the same way? I don't want to prompt user (again) for there password. – Jim Kennedy Mar 20 '14 at 19:58
  • Also, this should be noted, that if not ALL of your calls will be going through the proxy this could cause unexpected results. Most of the time a default web proxy should not be set unless you understand the implecations – Mutmatt Oct 18 '16 at 13:11
4

You could also try this :

Programmatically get whatever binding you are using,and then set the proxy on it directly e.g.

var binding = new WSDualHttpBinding("WSDualHttpBinding_IMainService");
binding.ProxyAddress = new Uri("http://192.168.5.1:3128");

where "WSDualHttpBinding_IMainService" is the name of your binding from your config file. Also you have to set UseDefaultWebProxy=false; otherwise your proxy will be ignored.

Ruben Bartelink
  • 55,135
  • 22
  • 172
  • 222
Layinka
  • 41
  • 1
1

I found a solution for someone who might use .NET Core 2.x

Which initially cause an issue when trying to set proxy by using

System.ServiceModel.BasicHttpBinding;

as answered by Cheeso.

You have to update WCF to the latest (v.4.7.0).

Go to NuGet Package Manager -> Update all related Project URL of WCF.

There must be:

  • System.ServiceModel.Security
  • System.ServiceModel.NetTcp
  • System.ServiceModel.Http
Warit Taveekarn
  • 111
  • 1
  • 4
  • Thanks a lot. I kept on running into "When using a non-null Proxy, the WindowsProxyUsePolicy property must be set to WindowsProxyUsePolicy.UseCustomProxy" This was the magic fix that worked. – Noel Feb 01 '21 at 23:23