We all know how to call a WCF service from .Net, but making the call from a .Net Core 3.1 web api or class library to a HTTPS WCF service is a bit tricky.
This solution is the recollection of many articles.
I am assuming you already have a .Net Core 3.1 web api project and some classes in your project.
This article will show how to create a new class that encapsulates de call to a HTTPS WCF web service, in our case it was a logging web service.
In your project we need to create the WCF proxy, very simple to do.
Current Setup and Environment
I am coding on Visual Studio 2019.
No special tools added yet (although I really need the latest Resharper).
Using GitLab (as a code repository).
Coding in .Net Core 3.1 (web api and classes).
Add Connected Service
Right click on your project > Add > Connected Service.
Choose the “Microsoft WCF Web Service Reference Provider”
Under URI, write the uri of the service, in my case, the wcf service was originally a regular HTTP but is now being redirected to a HTTPS port.
If you call the WCF web service using HTTP on Postman, it will return the HTML page corresponding to the HTTPS page.
But in this case, for the URI, I decided to enter the HTTP address and then on the constructor, use the HTTPS address. I am guessing choosing one over the other will not make a difference on the creation of the proxy reference.
Under Namespace, choose a descriptive name for your service, in this example is “MyServiceRef”.
Click Next, and make the next choices for Data Type Options:
- Always generate message contracts (not selected).
- Reuse types in referenced assemblies:
- Reuse types in ALL referenced assemblies (selected)
and Client Options:
- Access level for generated classes: Public.
- Generate Synchronous Operations (your call, in my case, I didn’t need this).
After a few minutes, the window dissapears and you should be presented with new classes in your project:
- ConnectedService.json
- Reference.cs
Dependencies
Here is a list of all dependencies needed to consume the HTTPS WCF web service from .Net Core 3.1 class library:
Adding Variables to appsettings.json
I wanted to add a variable to hold the value of the web service URI.
Almost always this is a good idea, as the URI might change for the different environments: Development, Production, etc.
A simple entry in appsettings.json will do:
"MyWebServiceSettings": { "MyWebServiceUrl": "https://myserver/MyWebService/LogTracker.asmx", }
Later, we will be calling for this configuration setting from our class.
Creating the Consumer .Net Core 3.1 Class Library
The idea of creating a class to encapsulate all the usage was that this was a logging WCF web service and was going to be consume from the web api as well as from the class libraries.
In the case of adding unit tests, having all these code in a class, would mean that it can also be consume from the test projects, without having to run on the web framework.
Also, I decided to make the class STATIC, which in my case meant I will not be able to use dependency injection to access the appsettings.json configuration file.
So, with that in mind it was my constructor the one in charge of reading and assigned the global variables, something like this:
private static readonly IConfiguration _configuration; private static string _myWebServiceUrl; static MyLogger() { _configuration = new ConfigurationBuilder() .AddJsonFile("appsettings.json") .Build(); _myWebServiceUrl = _configuration.GetSection("MyWebServiceSettings:MyWebServiceUrl").Value; }
Most of the time, the following code is enough to consume a regular HTTP WCF web service:
public async Task<WeatherReturn> GetWeather() { WeatherSoapClient client = new WeatherSoapClient(WeatherSoapClient.EndpointConfiguration.WeatherSoap); client.Endpoint.Address = _myWebServiceUrl ; WeatherReturn weatherReturn = await client.GetCityWeatherByZIPAsync("90210"); return weatherReturn; }
But for a HTTPS WCF call, you will need to add a Binding to your SOAP client.
One of the error messages related to calling a web service incorrectly is this one: “The provided URI scheme ‘https’ is invalid; expected ‘http’. (Parameter ‘via’)”
In my case, there was an error when trying to communicate without configuring the channel for HTTPS correctly: “The communication object, System.ServiceModel.ChannelFactory`1[MySvcRef.MySoap], cannot be used for communication because it is in the Faulted state.“, which is a horrible error message and hides the real reason of the error.
Once I added the correct configuration, everything works (even the redirection, without any issues):
try { System.ServiceModel.Channels.Binding binding = new BasicHttpBinding(BasicHttpSecurityMode.Transport); EndpointAddress endPointAddress = new EndpointAddress(_myWebServiceUrl ); WeatherSoapClient client = new WeatherSoapClient (binding, endPointAddress); // call your soapclient method client.SomeMethod(); } catch (Exception ex) { ... }
Once the BasicHttpBinding is configured with BasicHttpSecurityMode.Transport (notice I am not using the Https versions), the call can be completed and the result returns to the class.
If you like this article, and it help you in any way, please share it with your friends using Twitter or Facebook.