WCF: The remote server returned an error: "(417) Expectation Failed"
WCF: The remote server returned an error: "(417) Expectation Failed"
我们正在尝试从使用 NET Core 3.1 制作的后端服务连接到遗留 WCF 服务。为此,我们使用两个 NuGet 包“System.ServiceModel.Http”和“System.ServiceModel.Primitives”(最新版本 4.8.1)。
为了连接到端点,我们创建 binding/serviceclient 手册如下
var binding = new BasicHttpsBinding();
binding.Security.Mode = BasicHttpsSecurityMode.Transport;
binding.Security.Transport = new HttpTransportSecurity() { ClientCredentialType = HttpClientCredentialType.Certificate, ProxyCredentialType = HttpProxyCredentialType.Basic };
binding.CloseTimeout = new TimeSpan(0, 12, 0, 0, 0);
binding.OpenTimeout = new TimeSpan(0, 12, 0, 0, 0);
binding.SendTimeout = new TimeSpan(0, 12, 0, 0, 0);
binding.MaxReceivedMessageSize = 2147483646;
binding.MaxBufferSize = 2147483646;
var channelfactory = new SearchServiceClient(binding, endpoint);
channelfactory.ClientCredentials.ClientCertificate.SetCertificate(System.Security.Cryptography.X509Certificates.StoreLocation.CurrentUser, System.Security.Cryptography.X509Certificates.StoreName.My, System.Security.Cryptography.X509Certificates.X509FindType.FindBySubjectName, "CERTIFICATENAME");
var response = await channelfactory.existsAsync(...);
为了建立连接,我们需要使用 SSL 客户端证书,而不是 username/password。
对于每个请求,我们都会收到以下错误消息:“远程服务器返回错误:(417) 预期失败”。
我做了一些研究,发现您需要做的就是将“ExpectContinue”标志设置为 false。
不幸的是,这在 ServicePointManager 中不起作用(甚至在 web.config 中也不行)。
ServicePointManager.Expect100Continue = false;
如果我将“System.ServiceModel.Http”和“System.ServiceModel.Primitives”的 nuget 包版本降级到 4.4.4,它会起作用。
有谁知道我如何使用最新版本做到这一点?
经过几周的研究,我现在可以找到解决方案。
创建自定义 MessageHandlerBehavior 和 DelegatingHandler(请查看 https://justsimplycode.com/2019/11/02/disable-header-100-continue-in-net-core-wcf-client/)
使用自定义 MessageHandlerBehavior 并将 ExpectContinue 设置为 false:
var handlerFactoryBehavior = new HttpMessageHandlerBehavior();
handlerFactoryBehavior.OnSending = (message, token) =>
{
message.Headers.ExpectContinue = false;
return null;
};
var channelfactory = new SearchServiceClient(binding, endpoint);
channelfactory.ClientCredentials.ClientCertificate.SetCertificate(...);
channelfactory.Endpoint.EndpointBehaviors.Add(handlerFactoryBehavior);
我们正在尝试从使用 NET Core 3.1 制作的后端服务连接到遗留 WCF 服务。为此,我们使用两个 NuGet 包“System.ServiceModel.Http”和“System.ServiceModel.Primitives”(最新版本 4.8.1)。
为了连接到端点,我们创建 binding/serviceclient 手册如下
var binding = new BasicHttpsBinding();
binding.Security.Mode = BasicHttpsSecurityMode.Transport;
binding.Security.Transport = new HttpTransportSecurity() { ClientCredentialType = HttpClientCredentialType.Certificate, ProxyCredentialType = HttpProxyCredentialType.Basic };
binding.CloseTimeout = new TimeSpan(0, 12, 0, 0, 0);
binding.OpenTimeout = new TimeSpan(0, 12, 0, 0, 0);
binding.SendTimeout = new TimeSpan(0, 12, 0, 0, 0);
binding.MaxReceivedMessageSize = 2147483646;
binding.MaxBufferSize = 2147483646;
var channelfactory = new SearchServiceClient(binding, endpoint);
channelfactory.ClientCredentials.ClientCertificate.SetCertificate(System.Security.Cryptography.X509Certificates.StoreLocation.CurrentUser, System.Security.Cryptography.X509Certificates.StoreName.My, System.Security.Cryptography.X509Certificates.X509FindType.FindBySubjectName, "CERTIFICATENAME");
var response = await channelfactory.existsAsync(...);
为了建立连接,我们需要使用 SSL 客户端证书,而不是 username/password。
对于每个请求,我们都会收到以下错误消息:“远程服务器返回错误:(417) 预期失败”。
我做了一些研究,发现您需要做的就是将“ExpectContinue”标志设置为 false。
不幸的是,这在 ServicePointManager 中不起作用(甚至在 web.config 中也不行)。
ServicePointManager.Expect100Continue = false;
如果我将“System.ServiceModel.Http”和“System.ServiceModel.Primitives”的 nuget 包版本降级到 4.4.4,它会起作用。
有谁知道我如何使用最新版本做到这一点?
经过几周的研究,我现在可以找到解决方案。
创建自定义 MessageHandlerBehavior 和 DelegatingHandler(请查看 https://justsimplycode.com/2019/11/02/disable-header-100-continue-in-net-core-wcf-client/)
使用自定义 MessageHandlerBehavior 并将 ExpectContinue 设置为 false:
var handlerFactoryBehavior = new HttpMessageHandlerBehavior(); handlerFactoryBehavior.OnSending = (message, token) => { message.Headers.ExpectContinue = false; return null; }; var channelfactory = new SearchServiceClient(binding, endpoint); channelfactory.ClientCredentials.ClientCertificate.SetCertificate(...); channelfactory.Endpoint.EndpointBehaviors.Add(handlerFactoryBehavior);