2

I began a POC project yesterday to connect to an existing WCF service and I am using a .Net Core 2.1 Web API application and Swagger to post my test request messages. I am using BasicHttpBinding and Transport for BasicHttpSecurityMode.

When sending at test request message, I’m receiving the following exception:

"The HTTP request is unauthorized with client authentication scheme 'Anonymous'. The authentication header received from the server was 'Basic Realm'."

I then created a Microsoft Web API project using .NET Framework 4.6.1 to call the WCF service and I was able to get a Status Code 200 HTTP response.

This seems to me like an issue with a .NET Core 2 Web API project connecting to the WCF service. I’ve done some research and it looks like this design architecture should definitely be possible.

Microsoft has even developed a provider tool to do exactly this, here is a link to the MS article on the their provider tool: https://learn.microsoft.com/en-us/dotnet/core/additional-tools/wcf-web-service-reference-guide

I have even tried to have my .NET Core Web API controller call a handler class I built in a .NET 4.6.1 class library project to no avail, I still got the “The HTTP request is unauthorized with client authentication scheme 'Basic'. The authentication header received from the server was 'Basic Realm'.” exception.

private static System.ServiceModel.Channels.Binding GetBindingForEndpoint(EndpointConfiguration endpointConfiguration)
        {
            if ((endpointConfiguration == EndpointConfiguration.BasicHttpBinding_IInsuranceService))
            {
                System.ServiceModel.BasicHttpBinding result = new System.ServiceModel.BasicHttpBinding();
                result.MaxBufferSize = int.MaxValue;
                result.ReaderQuotas = System.Xml.XmlDictionaryReaderQuotas.Max;
                result.MaxReceivedMessageSize = int.MaxValue;
                result.AllowCookies = true;
                result.Security.Mode = System.ServiceModel.BasicHttpSecurityMode.Transport;
                return result;
            }
            throw new System.InvalidOperationException(string.Format("Could not find endpoint with name \'{0}\'.", endpointConfiguration));
        }

        private static System.ServiceModel.EndpointAddress GetEndpointAddress(EndpointConfiguration endpointConfiguration)
        {
            if ((endpointConfiguration == EndpointConfiguration.BasicHttpBinding_IInsuranceService))
            {
                return new System.ServiceModel.EndpointAddress("https://myservicebaseURL\myservice.svc");
            }
            throw new System.InvalidOperationException(string.Format("Could not find endpoint with name \'{0}\'.", endpointConfiguration));
        }
Timothy J
  • 41
  • 3
  • For `Basic` authentication, you need to configure `result.Security.Transport.ClientCredentialType = System.ServiceModel.HttpClientCredentialType.Basic;` And make sure you provide the right username and password by `this.ChannelFactory.Credentials.UserName.UserName = "yourusername"; this.ChannelFactory.Credentials.UserName.Password = "yourpassword";` – Edward Mar 28 '19 at 06:06
  • Thank you for your help. Unfortunately I have added the configuration settings you listed above to my service's Reference class and set the username and password credentials but I'm still getting the same exception. Could this be an issue with how Visual Studio is launching the app in IISExpress? – Timothy J Mar 28 '19 at 17:12
  • Below are settings from my launchSettings.json file: { "iisSettings": { "windowsAuthentication": false, "anonymousAuthentication": true, "iis": { "applicationUrl": "http://localhost/mywebapi", "sslPort": 0 }, "iisExpress": { "applicationUrl": "http://localhost:63143", "sslPort": 44331 } }, – Timothy J Mar 28 '19 at 17:15
  • How did you create the WCF Service? Is there any demo to reproduce your issue? – Edward Mar 29 '19 at 01:46

1 Answers1

2

Thanks for everyone's input. I was able to solve my problem by following the steps detailed in this article.

Please read below for my updated code to call the WCF service from my .NET Core 2 Web Api:

 public async Task<DataFetchServiceResponseUsingPatient> FetchEntity(String ID)
    {
      var userName = _authenticationSettings.Value.UserName;
      var password = _authenticationSettings.Value.Password;
      var url = _authenticationSettings.Value.Url;

      var basicHttpBinding = new BasicHttpBinding(BasicHttpSecurityMode.Transport);

      basicHttpBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;
      ChannelFactory<IMyService> factory = null;
      factory = new ChannelFactory<IMyService>(basicHttpBinding, new EndpointAddress(new Uri(url)));
      factory.Credentials.UserName.UserName = userName;
      factory.Credentials.UserName.Password = password;
      var serviceProxy = factory.CreateChannel();
      ((ICommunicationObject)serviceProxy).Open();
      var opContext = new OperationContext((IClientChannel)serviceProxy);
      var prevOpContext = OperationContext.Current;
      OperationContext.Current = opContext;

      var result = await serviceProxy.MyWCFServiceMethod(ID);

      //Cleanup Factory Objects
      factory.Close();
      ((ICommunicationObject)serviceProxy).Close();
      return result;    
    }
Timothy J
  • 41
  • 3