Running into a peculiar issue at work. Trying to connect to an https, custom client certificate based connected service. I'm using BasicHttpsBinding and ChannelFactory classes to create a client for the service.
Able to connect to the service and get the response back on a 3.1 console app but when i put the same code in a 3.1 Web API controller it fails when i try to call the same operation using the client with the error "There was no endpoint listening at .... This may be caused due to incorrect soap action". Inner exception says "winhttp exception. The server name or address could not be resolved".
I tried running fiddler to see what was different and for the console app i see a tunnel being established to the external service URL but for the call from within Web API I see nothing on Fiddler which means it's failing somewhere within the Web API pipeline itself.
Searches on Google point to checking proxy settings as this is on a corporate network but netsh winhttp show proxy shows direct (no proxy server) so i don't think it's a corporate proxy related issue.
What exactly is different in the network stack between a 3.1 console app and Web API that a WCF service call might fail in Web API but work in console app?
Code in question
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);
Have removed sensitive info like the service url and replaced the name of the interface generated on adding Connected Service to project by ExternalServiceInterface. Getting an exception at _client.ExternalServiceOperation() in .NET Core 3.1 Web API but works in .NET Core 3.1 Console App
Exception dump
{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()}
So, as it usually is, was really stupid on my part. But incase anyone else makes the same mistakes as me I'll list it out.
Updating the System.ServiceModel.*
Nuget Packages to their latest versions(from 4.4.0 -> 4.7.0) resolved this issue for me, don't know why older versions were being automatically installed when adding the WCF/Connected Service.
Had read up that newer versions of .NET Core no longer use WinHttp and instead use SocketsHttpHandler, and that should have alerted me to an old library being used as I was seeing a WinHttpException
And as to why it was working in a console app for me. I had 4.4.0 versions of the libraries there as well, but apparently to fix some reference error, I had manually installed System.Private.ServiceModel
which is a dependency of System.ServiceModel
and doesn't usually require manual installation. And I installed the 4.7.0 version of System.Private.ServiceModel
. This somehow made the WCF service call work in the console app, even with the version mismatch between System.Private.ServiceModel
and System.ServiceModel
packages
Github issue thread that led me to check the library version, with more details on why exactly old versions of library cause errors - https://github.com/dotnet/wcf/issues/3311