Stuck on connection to WSDL in VS2019 - c#

I have tried what seems like a million ways, and I might have confused myself to the point of too much frustration. I am very much a beginner in terms of WSDL. Ran through a calculator tutorial.
The task at hand is connecting to a WSDL Webservice from a Danish state department. (since the addresses are publicly available, so I see no reason to hide them.)
I have confirmed that the Soap webservice is working and is functional by using SoapUI 5.5.0, by following a guide from the department.
To begin with what I have been trying to do is create a very simple console application with hardcoded information, just to test out the C# code / the workflow. The final product is either going to be a MVC .Net or Blazor server.
I have removed the Username and password from the code and the request information which is a 10 digit code in string format. They have been replaced with ".....".
This Is the wsdl address: https://ws.fvst.dk/service/CHR_dyrWS?WSDL
All the information I have gathered. The steps for using a webservice is adding it via connected services and instantiating it, adding user information and calling the request function in the webservice and lastly fixing the config to using authentication.
But no matter what I do it seems like I cannot make it work, it throws a validation error or a Security.MessageSecurityException.
The code I currently have
using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.Text;
using System.Threading.Tasks;
using ConsoleApp5.ServiceReference1;
namespace ConsoleApp5
{
class Program
{
static void Main(string[] args)
{
CHR_dyrWSClient client = new CHR_dyrWSClient();
var basicHttpBinding = new BasicHttpBinding(BasicHttpSecurityMode.TransportWithMessageCredential);
basicHttpBinding.Security.Message.ClientCredentialType = BasicHttpMessageCredentialType.UserName;
basicHttpBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;
client.ClientCredentials.UserName.UserName = ".....";
client.ClientCredentials.UserName.Password = ".....";
ServiceReference1.CHR_dyrHentCkrOplysningerRequest requestInfo = new ServiceReference1.CHR_dyrHentCkrOplysningerRequest();
requestInfo.Request.CkrNr = ".....";
var responseInfo = client.hentCkrOplysninger(requestInfo);
Console.WriteLine(responseInfo.Response);
client.Close();
}
}
}
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
</startup>
<system.serviceModel>
<bindings>
<basicHttpsBinding>
<binding name="CHR_dyrWSPortBinding">
<security mode="TransportWithMessageCredential">
<message clientCredentialType="UserName" />
</security>
</binding>
</basicHttpsBinding>
</bindings>
<client>
<endpoint
address="https://ws.fvst.dk:443/service/CHR_dyrWS"
binding="basicHttpsBinding"
bindingConfiguration="CHR_dyrWSPortBinding"
contract="ServiceReference1.CHR_dyrWS"
name="CHR_dyrWSPort" />
</client>
</system.serviceModel>
</configuration>
I would really like to know where I need to go from here. I am really unsure if I’m connecting to the webservice wrong? The thing that I am most unsure about is the way you need to connect to this web service.
Any help or links would be greatly appreciated!
Kind regards

I have figured it out. I needed to send the optional information in the soap request too.
and i needed to specify a header in the app.config file.
To make it work i copied to header information from SoapUI in the http log.
Pasted it in the header information in the app.config. The username token can be removed and will still work.
The entire program code
Config file
Console output

Related

consuming webservice using https protocol

I'm developing an application where i have to consume webservice developed in Java using http protocol.
I'm developing the application using C#.NET winforms. Everything works fine until now. The webservice is now using SSL security hence the service protocol changed from http to https. I'm facing issues while accessing the https webservice.
I tried accessing the https webservice from the SoapUI by providing the Authenticaion Parameters (UserName and Password) from the Auth tab as shown below:
It is working fine from SoapUI.
but wen i provide the Authenticaion parameters from code as below its not working:
client.ClientCredentials.UserName.UserName = "admin";
client.ClientCredentials.UserName.Password = "*******";
I'm using Security Mode as : TransportWithMessageCredential
and
ClientCredentialTtype as : Basic
My App.Config file is as below:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<system.serviceModel>
<client>
<endpoint address="https://xyz:8001/HelloWorldAPI/HelloWorldWebService"
binding="wsHttpBinding"
bindingConfiguration="myhttpsbinding" contract="API.HelloWorldWebService"
name="HelloWorldWebServicePort" />
</client>
<bindings>
<wsHttpBinding>
<binding name="myhttpsbinding">
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="Basic"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
</system.serviceModel>
<system.net>
<defaultProxy useDefaultCredentials="true" />
</system.net>
</configuration>
My Code as below:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.ServiceModel;
using System.Text;
using System.Threading.Tasks;
using testingtool.API;
namespace testingtool
{
class Program
{
static void Main(string[] args)
{
new APITool();
}
}
class APITool
{
UserInfo userinfo = new UserInfo();
HelloWorldWebServiceClient client = new HelloWorldWebServiceClient();
private bool ValidationCallBack(object sender, X509Certificate cert, X509Chain chain, System.Net.Security.SslPolicyErrors error)
{
return true;
}
public APITool()
{
try
{
//Authentication parameters
client.ClientCredentials.UserName.UserName = "admin";
client.ClientCredentials.UserName.Password = "*****";
ServicePointManager.ServerCertificateValidationCallback = new System.Net.Security.RemoteCertificateValidationCallback(ValidationCallBack);
//client ClientCredentials # Application level
userinfo.userid = "myusername";
userinfo.password = "*****";
GetHelloWorldAPIVersionRequest request = new GetHelloWorldAPIVersionRequest();
APIVersionInfo versioninfo = new APIVersionInfo();
versioninfo.userinfo = userinfo;
request.APIVersionInfo = versioninfo;
APIVersionInfoResponse response = client.GetHelloWorldAPIVersion(versioninfo);
Console.WriteLine(response.Version);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
Console.ReadLine();
}
}
}
I'm getting following exception:
System.ServiceModel.Security.MessageSecurityException: The HTTP
request is unauthorized with client authentication scheme 'Anonymous'.
The authentication header received from the server was 'Basic
realm="EJBServiceEndpointServlet Realm"'. --->
System.Net.WebException: The remote server returned an error: (401)
Unauthorized.
EDIT: from the client i have verified with Fiddler the request window as below:
from the AUth tab it is saying that there is no Autherization Header present.
Fiddler Raw Request as below:
CONNECT 10.10.10.110:8001
HTTP/1.1 Host: 10.10.10.110:8001
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.1.1 (java 1.5)
Any help wouldbe greatly appreciated.
Wondering if the issue could be with the binding, although hard to say for sure without reviewing the service configuration or seeing the successful soapUI request. (Note: you may want to include a snippet of the message, including the soap header, from the soapUI HTTP Log.)
In any case, you may want to make sure the service is really using ws-security (message level security) by trying the following binding:
<bindings>
<basicHttpBinding>
<binding name="httpBinding">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Basic" />
</security>
</binding>
</basicHttpBinding>
</bindings>
You should change your app config:
<wsHttpBinding>
<binding name="myhttpsbinding">
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="None" />
<message clientCredentialType="UserName" establishSecurityContext="false" negotiateServiceCredential="false"/>
</security>
</binding>
</wsHttpBinding>
On transport level you have no authentication, so <transport clientCredentialType="None" /> and on message level you have username|password authentication, so <message clientCredentialType="UserName"
are you going thru a proxy server? If yes, are the details entered into IE ? Are you able to browse https pages in IE? If yes, this should be picked up by each WebRequest that makes an https call as it needs to issue a CONNECT to the proxy server (which its doing) but in your call the Proxy-Authorization header is missing. This should be your focus - try a plain WebRequest to say https:// google.com and see what you get in fiddler.
You may have an issue with your proxy server forwarding on your request. Are you able to try https on a different network not behind a proxy?
Maybe this link can help.
It explains how to configure your endpoint in case of REST/SOAP WebServices
Can not call web service with basic authentication using WCF
I have given <security mode="Transport" /> inside binding and issue solved for calling HTTPS service. Full code:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="ServiceSoap">
<security mode="Transport" />
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="https://yourlink/Service.asmx" binding="basicHttpBinding" bindingConfiguration="ServiceSoap" contract="EmployeeService.ServiceSoap" name="ServiceSoap"/>
</client>
</system.serviceModel>
Its binding issue you need to use custom binding here is example.
http://webservices20.blogspot.com/

Define which Endpoint to use when consuming a Web Service

I'm new to .NET and have been following this tutorial (http://johnwsaunders3.wordpress.com/2009/05/17/how-to-consume-a-web-service/) to consume a simple weather web service. My small console application essentially asks the user for a ZIP code, fires that to the web service then returns to response in the console. At least, that's the way it should work.
The web service I am using is:
http://wsf.cdyne.com/WeatherWS/Weather.asmx
The problem with this is there are multiple endpoints for different ways of consuming the service:
SOAP 1.1
SOAP 1.2
HTTP GET
HTTP POST
Because of this, when I run the console application, I am presented with the following error:
Unhandled Exception: System.InvalidOperationException: An endpoint configuration section for contract 'Service1Reference.WeatherSoap'
could not be loaded because more than one endpoint configuration for that contract was found. Please indicate the preferred endpoint configuration section by name.
My question is, how do I specify that my call to the web service should use one of the SOAP endpoints?
My code so far can be found below:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ConsoleApplication1.Service1Reference;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Console.Write("Enter ZipCode: ");
var line = Console.ReadLine();
if (line == null)
{
return;
}
WeatherSoapClient svc = null;
bool success = false;
try
{
svc = new WeatherSoapClient();
var request = line;
var result = svc.GetCityForecastByZIP(request);
Console.WriteLine("The result is:");
Console.WriteLine(result);
Console.Write("ENTER to continue:");
Console.ReadLine();
svc.Close();
success = true;
}
finally
{
if (!success && svc != null)
{
svc.Abort();
}
}
}
}
}
Any help with this would be greatly appreciated.
Edit:
The contents of my App.config file can be found here:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="WeatherSoap" />
</basicHttpBinding>
<customBinding>
<binding name="WeatherSoap12">
<textMessageEncoding messageVersion="Soap12" />
<httpTransport />
</binding>
</customBinding>
</bindings>
<client>
<endpoint address="http://wsf.cdyne.com/WeatherWS/Weather.asmx"
binding="customBinding" bindingConfiguration="WeatherSoap12"
contract="Service1Reference.WeatherSoap" name="WeatherSoap12" />
</client>
</system.serviceModel>
</configuration>
It seems as though .NET is trying to be helpful in generating a SOAP 1.2 binding for you when you probably don't need it (see this question for more information).
To work around this you can explicitly tell the service client which binding to use when you instantiate it by specifying the endpoint name to use:
svc = new WeatherSoapClient("WeatherSoap");
Where "WeatherSoap" is the value of the name attribute on your endpoint node.

What works as a Web Refence(ASMX) should work as a Service Reference(WCF), correct?

I've recently noticed that using Service References(WCF) causes problems with plain old SOAP API's. I thought that the newer more improved approach was to use Service References because WCF is more flexible and modern. Can anyone detect how I can make this work with WCF in VS2013?
It is a simple console app trying to consume RxNav (free) api
URL: http://mor.nlm.nih.gov/axis/services/RxNormDBService
After adding a "Service Reference" to the solution I entered the following code:
Program.cs
static void Main(string[] args)
{
var client = new RxNavAPI.DBManagerClient();
try
{
var matches = client.getDrugs("aspirin");
foreach (var conceptGroup in matches)
{
foreach (var concept in conceptGroup.rxConcept)
{
Console.WriteLine(String.Format("Name: {0}, Syn: {1}", concept.STR, concept.SY));
}
}
client.close();
}
catch (TimeoutException ex)
{
Console.WriteLine("Timeout occurred while accessing RxNav API");
Console.WriteLine(ex.Message);
throw;
}
}
App.config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.1" />
</startup>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="RxNormDBServiceSoapBinding" />
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://mor.nlm.nih.gov/axis/services/RxNormDBService"
binding="basicHttpBinding" bindingConfiguration="RxNormDBServiceSoapBinding"
contract="RxNavAPI.DBManager" name="RxNormDBService" />
</client>
</system.serviceModel>
</configuration>
One thing that I have noticed is when added as a Web Reference the client is called like:
var client = new RxNavAPI.DBManagerService();
while when using Service Reference it is like:
var client = new RxNavAPI.DBManagerClient();
EDIT: The error I am receiving is
System.InvalidOperationException : "RPC Message
getProprietaryInformationRequest1 in operation
getProprietaryInformation1 has an invalid body name
getProprietaryInformation. It must be getProprietaryInformation1"
Awesome!
#John Saunders answering everywhere.
This is the same issue noted over 5 years ago. WCF: Svcutil generates invalid client proxy, Apache AXIS Web Service, overload operations
Now I'm having the same issue and there is still no fix, only workarounds for this.

Consuming Web Services - Confusion on Setup

I recently added a remote WSDL file for a web service to my app_webreferences folder.
I can see all the objects in that WSDL file - however, the problem is that the company that i'm integrating with sent me two urls.
a wsdl: https://website.com/SOAP/Queue?wsdl
an endpoint: https://website.com/SOAP/Queue?api_key=xxxxxx
So - when I added the app_webreference I used the first url - it worked, added it to project.
I then proceeded to setup my bindings as such:
<wsHttpBinding>
<binding name="QueueWebServiceBinding">
<security mode="TransportWithMessageCredential">
<message clientCredentialType="UserName" />
</security>
</binding>
</wsHttpBinding>
My client endpoint looks like this:
<endpoint address="https://website.com/SOAP/Queue?wsdl"
binding="wsHttpBinding" bindingConfiguration="QueueWebServiceBinding"
contract="MyWebService" name="QueueWebServicePort" />
</client>
The thing is, I cannot for the life of me get this to work. I'm not sure where I should use the endpoint url (#2) in any of this. It seems that when I switch it out in the endpoint address (#2) above I receive a response of:
...<env:Fault..... does not contain operation meta data for ... </env:Fault>...
I'm really confused on how to set this all up.
Another thing to note, they do require authentication... so my actual code looks something like this...
MyWebServiceClient client = new MyWebServiceClient();
client.ClientCredentials.UserName.UserName = "username";
client.ClientCredentials.UserName.Password = "password";
var t = client.doSomething();
I've been googling/searching stackoverflow for the past few hours but have had little success figuring out the right way to set this all up.
Appreciate any help.
The first endpoint is for the WSDL. The second endpoint is for the actual service itself. So you need to change your endpoint in your config file as follows:
<client>
<endpoint address="https://website.com/SOAP/Queue?api_key=xxxxxx"
binding="wsHttpBinding"
bindingConfiguration="QueueWebServiceBinding"
contract="MyWebService" name="QueueWebServicePort" />
</client>
Since you've already tried switching out the endpoint, try using the second endpoint to add the service reference and see if that works (if you haven't already).
If neither of those work, then I'd suggest talking to the vendor's support staff to see if they can help, since they should know everything you need to do to access the service.

WCF client not mapping and returning null objects

I've setup a Service Reference (WCF Client) to call a Java Web Service from a Console Application I've setup for testing. It is using HTTPS. I have Fiddler setup and can see the proper values being sent and returned from the service (in Fiddler). But no matter what method I call, the returned values, regardless if it is a String or an object, comes back as Null.
I'm not sure if the proxy client mapping isn't working or if I need to change a configure value in app.config.
app.config:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<system.serviceModel>
<bindings>
<customBinding>
<binding name="ResultsSOAP12Binding">
<textMessageEncoding messageVersion="Soap12" />
</binding>
<binding name="ResultsSOAP12Binding1">
<textMessageEncoding messageVersion="Soap12" />
<httpsTransport />
</binding>
<binding name="ResultsSOAP12Binding2">
<textMessageEncoding messageVersion="Soap12" />
</binding>
</customBinding>
</bindings>
<client>
<endpoint address="https://services.acme.com/results"
binding="customBinding" bindingConfiguration="ResultsSOAP12Binding1"
contract="ResultsServiceReference.Result
</client>
</system.serviceModel>
</configuration>
Code:
static void CallResults()
{
var resultsRequest = new ResultsServiceReference.ResultsRequest();
var client = new ResultsServiceReference.ResultsPortTypeClient("ResultsSOAP12BindingQSPort");
Console.WriteLine("Call Results Service");
ResultsServiceReference.ResultsBatch result = client.latestResults(resultsRequest);
Console.WriteLine(result.Status);
Console.ReadLine();
}
In this code the variable result is null, even though when you look in Fiddler you can see the XML. No error is displayed until you try to use result.
BTW, I tried setting a breakpoint inside the latestResults method in the proxy class reference.cs, but the debugger doesn't reach it.
You may want to configure and enable WCF diagnostic event tracing and message logging, then rerun the test transaction and review the service trace log file. The following link demonstrates how to enable tracing and message logging.
http://msdn.microsoft.com/en-us/library/ms751526.aspx
In our experience, service discrepancies which otherwise show no obvious error, often show up in the service trace file.
Note: The breakpoint inside the proxy class reference.cs may not be reached because the following attribute has been set:
[System.Diagnostics.DebuggerStepThroughAttribute()]
Most probably the WSDL has a mistake and the schema inside it does not match the actual response XML. You can publish the WSDL (and any referenced XSD) here together with the SOAP response (or mail them to me so I will try to look). Or you can set up a WCF service stub from the exact same WSDL (or from the client contract you already generated) and compare the response WCF sends to the one the actual service sends.
You want to look for differences in XML namespaces (and understand delicate parts like if this is default namespace or prefixed one) and in the name of the first element under the body.

Categories

Resources