Служба Wcf работает в консольном приложении. NET Core 3.1, но не работает в ASP. NET Core 3.1 Web API - PullRequest
0 голосов
/ 29 марта 2020

Встречается с особой проблемой на работе. Попытка подключиться к https, подключенной службе на основе пользовательского сертификата клиента. Я использую классы BasicHttpsBinding и ChannelFactory для создания клиента для службы.

Возможность подключиться к службе и получить ответ обратно в консольном приложении 3.1, но когда я помещаю тот же код в веб-API 3.1 Контроллер не работает, когда я пытаюсь вызвать ту же операцию, используя клиент с ошибкой "Не было прослушивания конечной точки .... Это может быть вызвано неправильным действием soap". Внутреннее исключение говорит: «исключение winhttp. Имя или адрес сервера не могут быть разрешены» .

Я попытался запустить fiddler, чтобы увидеть, что отличалось, и для консольного приложения я вижу туннель, устанавливаемый для внешнего URL-адрес службы, но для вызова изнутри Web API я ничего не вижу в Fiddler, что означает, что он не работает где-то в самом конвейере Web API.

Поиск в Google указывает на проверку настроек прокси, так как это происходит в корпоративной сети, но netsh winhttp show proxy показывает direct (без прокси-сервера) , поэтому я не думаю, что это проблема, связанная с корпоративным прокси.

Что именно отличается в сетевом стеке между консольным приложением 3.1 и веб-API тем, что вызов службы WCF может завершиться ошибкой в ​​веб-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. Получение исключения в _client.ExternalServiceOperation () in. NET Core 3.1 Web API, но работает в. NET Core 3.1 Console App

Дамп исключения

{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()}

1 Ответ

0 голосов
/ 29 марта 2020

Так что, как обычно, было действительно глупо с моей стороны. Но если кто-нибудь еще совершит те же ошибки, что и я, я перечислю это.

Обновление System.ServiceModel.* пакетов Nuget до их последних версий (с 4.4.0 -> 4.7.0) решило эту проблему для меня, не знаю, почему старые версии автоматически устанавливались при добавлении WCF / Подключенный Сервис.

Прочитал, что более новые версии. NET Ядро больше не использует WinHttp и вместо этого использует SocketsHttpHandler, и это должно было предупредить меня об использовании старой библиотеки, поскольку я видел WinHttpException

А что касается того, почему он работал в консольном приложении для меня. У меня там также были версии библиотек 4.4.0, но, по-видимому, для исправления некоторой ссылочной ошибки я вручную установил System.Private.ServiceModel, который зависит от System.ServiceModel и обычно не требует ручной установки. И я установил 4.7.0 версию System.Private.ServiceModel. Это как-то заставило вызов службы WCF работать в консольном приложении, даже при несовпадении версий между System.Private.ServiceModel и System.ServiceModel пакетами

Поток выпуска Github, который побудил меня проверить версию библиотеки, с более подробной информацией о причинах именно старые версии библиотеки вызывают ошибки - https://github.com/dotnet/wcf/issues/3311

...