首页 > 解决方案 > WCF:远程服务器返回错误:“(417)预期失败”

问题描述

我们正在尝试从使用 NET Core 3.1 制作的后端服务连接到旧版 WCF 服务。为此,我们使用两个 NuGet 包“System.ServiceModel.Http”和“System.ServiceModel.Primitives”(最新版本 4.8.1)。

对于到端点的连接,我们创建绑定/服务客户端手册如下

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 客户端证书,而不是用户名/密码。

对于每个请求,我们都会收到以下错误消息:“远程服务器返回错误:(417) 预期失败”。

我做了一些研究,发现您需要做的就是将“ExpectContinue”标志设置为false。

不幸的是,这不能通过 ServicePointManager 工作(甚至在 web.config 中也不行)。

ServicePointManager.Expect100Continue = false;

如果我将“System.ServiceModel.Http”和“System.ServiceModel.Primitives”的nuget包版本降级到4.4.4,它可以工作。

有谁知道我如何使用最新版本来做到这一点?

标签: wcf.net-core

解决方案


经过几周的研究,我现在可以找到解决方案。

  1. 创建自定义 MessageHandlerBehavior 和 DelegatingHandler(请查看https://justsimplycode.com/2019/11/02/disable-header-100-continue-in-net-core-wcf-client/

  2. 使用自定义 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);
    

推荐阅读