如何为SoapPortClient设置代理(地址及凭据)解决WS功能失效问题?
解决SoapPortClient无法设置Proxy属性的问题
遇到这种情况很常见——你用的应该是WCF生成的服务客户端(通过添加服务引用创建的SoapPortClient),这类客户端和旧的ASMX Web引用客户端不同,并没有直接暴露Proxy属性,而是需要通过绑定配置或者自定义Endpoint行为来设置代理。下面给你两种可行的解决方案:
方法一:直接修改绑定的代理设置
如果你的WebService用的是基础HTTP绑定(比如BasicHttpBinding),可以直接获取客户端的绑定实例,然后配置代理地址和凭据:
Namespace.WebService.SoapPortClient foo = new Namespace.WebService.SoapPortClient(); // 将绑定转换为对应的类型(如果是WSHttpBinding就换成WSHttpBinding) var basicBinding = foo.Endpoint.Binding as BasicHttpBinding; if (basicBinding != null) { // 设置代理服务器地址 basicBinding.ProxyAddress = new Uri("http://your-proxy-server:port"); // 关闭系统默认代理,使用我们指定的代理 basicBinding.UseDefaultWebProxy = false; // 设置代理的凭据类型(根据你的代理服务器要求选,比如NTLM、Basic) basicBinding.Security.Transport.ProxyCredentialType = HttpProxyCredentialType.Basic; // 设置代理的登录凭据 foo.ClientCredentials.Windows.ClientCredential = new System.Net.NetworkCredential("proxy-username", "proxy-password"); // 如果代理用的是Basic认证,也可以用下面的方式(二选一即可) // foo.ClientCredentials.UserName.UserName = "proxy-username"; // foo.ClientCredentials.UserName.Password = "proxy-password"; } // 之后正常调用你的方法 short cod_error; string des_error; string url = ""; int fooNumber = 10; url = foo.Execute(fooNumber, out cod_error, out des_error);
方法二:使用自定义Endpoint行为配置代理
如果需要更灵活的代理控制(比如动态修改代理、添加额外的请求头),可以创建一个自定义的Endpoint行为来实现:
首先定义行为类和消息检查器:
using System; using System.Net; using System.Text; using System.ServiceModel; using System.ServiceModel.Channels; using System.ServiceModel.Description; using System.ServiceModel.Dispatcher; public class ProxyConfigBehavior : IEndpointBehavior { private readonly Uri _proxyUri; private readonly NetworkCredential _proxyCreds; public ProxyConfigBehavior(Uri proxyUri, NetworkCredential proxyCreds) { _proxyUri = proxyUri; _proxyCreds = proxyCreds; } public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) { // 找到HTTP传输绑定元素,设置代理地址 var httpTransport = endpoint.Binding.CreateBindingElements() .OfType<HttpTransportBindingElement>() .FirstOrDefault(); if (httpTransport != null) { httpTransport.ProxyAddress = _proxyUri; httpTransport.UseDefaultWebProxy = false; httpTransport.ProxyCredentialType = HttpProxyCredentialType.Basic; } } public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime) { // 添加消息检查器,处理代理凭据的请求头 clientRuntime.ClientMessageInspectors.Add(new ProxyCredentialInspector(_proxyCreds)); } // 下面两个方法不需要实现,留空即可 public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher) { } public void Validate(ServiceEndpoint endpoint) { } } public class ProxyCredentialInspector : IClientMessageInspector { private readonly NetworkCredential _creds; public ProxyCredentialInspector(NetworkCredential creds) { _creds = creds; } public object BeforeSendRequest(ref Message request, IClientChannel channel) { var httpRequestProp = (HttpRequestMessageProperty)request.Properties[HttpRequestMessageProperty.Name]; if (httpRequestProp != null && _creds != null) { // 生成Basic认证的头部 string authToken = Convert.ToBase64String(Encoding.UTF8.GetBytes($"{_creds.UserName}:{_creds.Password}")); httpRequestProp.Headers["Proxy-Authorization"] = $"Basic {authToken}"; } return null; } public void AfterReceiveReply(ref Message reply, object correlationState) { } }
然后在你的客户端代码中使用这个行为:
Namespace.WebService.SoapPortClient foo = new Namespace.WebService.SoapPortClient(); // 配置代理地址和凭据 var proxyUri = new Uri("http://your-proxy-server:port"); var proxyCreds = new NetworkCredential("proxy-username", "proxy-password"); // 将自定义行为添加到客户端端点 foo.Endpoint.Behaviors.Add(new ProxyConfigBehavior(proxyUri, proxyCreds)); // 正常调用方法 short cod_error; string des_error; string url = ""; int fooNumber = 10; url = foo.Execute(fooNumber, out cod_error, out des_error);
为什么找不到Proxy属性?
简单说,这是因为你用的是WCF服务客户端(通过"添加服务引用"生成),而旧的ASMX Web引用客户端(通过"添加Web引用"生成)才会直接暴露Proxy属性。WCF的设计更倾向于通过绑定和行为来统一配置通信细节,包括代理、安全等。
如果不确定自己的客户端类型,可以检查生成的SoapPortClient类的基类——如果继承自ClientBase<T>,那就是WCF客户端,用上面的方法就可以解决问题。
内容的提问来源于stack exchange,提问作者Luciano Bertello
相关产品推荐
相关产品推荐

