Wcf服务可在.NET Core 3.1控制台应用程序中工作,但无法在ASP.NET Core 3.1 Web API中



在工作中遇到特殊问题。正在尝试连接到基于https的自定义客户端证书连接服务。我正在使用BasicHttpsBinding和ChannelFactory类为该服务创建一个客户端。

能够连接到服务并在3.1控制台应用程序上获取响应,但当我在3.1 Web API控制器中放入相同的代码时,当我尝试使用客户端调用相同的操作时失败,并返回错误"没有端点在侦听……这可能是由于不正确的soap操作造成的"。内部异常显示"winhttp异常。无法解析服务器名称或地址">

我试着运行fiddler来看看有什么不同,对于控制台应用程序,我看到正在建立一个到外部服务URL的隧道,但对于来自Web API的调用,我在fiddler上看不到任何东西,这意味着它在Web API管道本身的某个地方失败了。

在谷歌上搜索指向检查代理设置,因为这是在公司网络上,但netsh winhttp show proxy显示direct(无代理服务器(,所以我不认为这是与公司代理相关的问题。

3.1控制台应用程序和Web API之间的网络堆栈中到底有什么不同,即WCF服务调用可能在Web API中失败,但在控制台应用程序中工作

有问题的代码

var binding = new BasicHttpsBinding();
binding.Security.Mode = BasicHttpsSecurityMode.Transport;
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
var endpoint = new EndpointAddress(new Uri("https://service url"));
var channelFactory = new ChannelFactory<ExternalServiceInterface>(binding, endpoint);
channelFactory.Credentials.ClientCertificate.Certificate = new X509Certificate2(certificatepath, password);
_client = channelFactory.CreateChannel();
var sbmtGtDtResp = _client.ExternalServiceOperation(data);

已删除敏感信息,如服务url,并替换ExternalServiceInterface在将Connected service添加到项目时生成的接口名称。在.NET Core 3.1 Web API中的_client.ExternalServiceOperation((处获取异常,但在.NET Core 310控制台应用程序中有效

异常转储

{System.ServiceModel.EndpointNotFoundException: There was no endpoint listening at "https://service url" that could accept the message. This is often caused by an incorrect address or SOAP action. See InnerException, if present, for more details.
---> System.Net.Http.HttpRequestException: An error occurred while sending the request.
---> System.Net.Http.WinHttpException (80072EE7, 12007): The server name or address could not be resolved
at System.Threading.Tasks.RendezvousAwaitable`1.GetResult()
at System.Net.Http.WinHttpHandler.StartRequest(WinHttpRequestState state)
--- End of inner exception stack trace ---
at System.ServiceModel.Channels.ServiceModelHttpMessageHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
at System.Net.Http.HttpClient.FinishSendAsyncUnbuffered(Task`1 sendTask, HttpRequestMessage request, CancellationTokenSource cts, Boolean disposeCts)
at System.ServiceModel.Channels.HttpChannelFactory`1.HttpClientRequestChannel.HttpClientChannelAsyncRequest.SendRequestAsync(Message message, TimeoutHelper timeoutHelper)
--- End of inner exception stack trace ---
at System.ServiceModel.Channels.HttpChannelUtilities.ProcessGetResponseWebException(HttpRequestException requestException, HttpRequestMessage request, HttpAbortReason abortReason)
at System.ServiceModel.Channels.HttpChannelFactory`1.HttpClientRequestChannel.HttpClientChannelAsyncRequest.SendRequestAsync(Message message, TimeoutHelper timeoutHelper)
at System.ServiceModel.Channels.RequestChannel.RequestAsync(Message message, TimeSpan timeout)
at System.ServiceModel.Channels.RequestChannel.RequestAsyncInternal(Message message, TimeSpan timeout)
at System.Runtime.TaskHelpers.WaitForCompletionNoSpin[TResult](Task`1 task)
at System.ServiceModel.Channels.RequestChannel.Request(Message message, TimeSpan timeout)
at System.ServiceModel.Dispatcher.RequestChannelBinder.Request(Message message, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs)
at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(MethodCall methodCall, ProxyOperationRuntime operation)
at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(MethodInfo targetMethod, Object[] args)
--- End of stack trace from previous location where exception was thrown ---
at System.Reflection.DispatchProxyGenerator.Invoke(Object[] args)
at generatedProxy_1.submitGetDataRequest(submitGetDataRequestRequest )
at WebAPIPOC.Controllers.ServiceController.Process() in "Code filepath.cs":line 50
at lambda_method(Closure , Object , Object[] )
at Microsoft.Extensions.Internal.ObjectMethodExecutor.Execute(Object target, Object[] parameters)
at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.SyncObjectResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeActionMethodAsync()
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeNextActionFilterAsync()}

所以,就像往常一样,我真的很愚蠢。但如果其他人也犯了和我一样的错误,我会把它列出来。

System.ServiceModel.*Nuget软件包更新到其最新版本(从4.4.0->4.7.0(为我解决了这个问题,我不知道为什么在添加WCF/Connected服务时会自动安装旧版本。

已经读到.NET Core的新版本不再使用WinHttp,而是使用SocketsHttpHandler,这应该提醒我使用旧库,因为我看到了WinHttpException

至于为什么它在控制台应用程序中对我有效。我在那里也有4.4.0版本的库,但显然是为了修复一些参考错误,我手动安装了System.Private.ServiceModel,这是System.ServiceModel的依赖项,通常不需要手动安装。我安装了System.Private.ServiceModel的4.7.0版本。这以某种方式使WCF服务调用在控制台应用程序中工作,即使System.Private.ServiceModelSystem.ServiceModel包之间的版本不匹配

Github问题线程让我检查了库的版本,并详细说明了为什么旧版本的库会导致错误https://github.com/dotnet/wcf/issues/3311

我花了6个小时试图解决这个问题。在我的案例中,我试图在控制台中使用肥皂,结果得到了";没有在侦听的终结点https://swea.riksbank.se/sweaWS/services/SweaWebServiceHttpSoap12Endpoint可以接受消息soap";错误在访问了这个答案之后,我将所有ServiceModel包:System.ServiceModel.DuplexSystem.ServiceModel.HttpSystem.ServiceModel.NetTcpSystem.ServiceModel.Security更新到v4.7.0,现在它正在正确地获得响应。虽然目前的问题和公认的答案是针对netcore3.1的,但我的控制台应用程序在dotnetcore 2.1中,所以我认为它与整个wsdl导入过程有关,因为包是通过脚手架过程安装的。

最新更新