Accessing SOAP Webservice Problems - c#

at the moment Iam working as a working student at a Software Company and I got the task to setup a client who works with a webservice from a third party (only have a wsdl-, xsd file and user certificate).
I read a lot about Webservices in the last time and I did a lot of tutorials, but I did not manage to connect to the Server and make a simple test request.
I have a Windowsform Application an added a Service reference to the project via the physical path of the wsdl document. From this the generated proxy classes.
The wsdl and xsd file you can find here [https://www.dropbox.com/sh/qgopygt9gtbhwq6/AADHp8k1ktfNrzMVKCjQ0EsPa?dl=0][1]
EndpointAddress ea = new EndpointAddress("https://212.62.77.106:9443/hapwebservices/secure_routed/dms");
DMSServiceClient client = new DMSServiceClient(new BasicHttpsBinding(), ea);
X509Certificate2 cert = new X509Certificate2(#"C:\Users\myName\Desktop\DMS-test-2016.p12", "privateKey");
client.ClientCredentials.ClientCertificate.Certificate = cert;
Header header = new Header();
header.InputTime = DateTime.Now;
header.SystemId ="TheSystemID";
header.OrganisationId = "TheOrganisationID";
header.Password = "Password";
header.OrganisationName = "Oraganisation";
header.InterfaceVersion="3.0";
header.DMSVersion = "1";
header.DMSName = "DMSNAME";
DateTime datetime = DateTime.Now;
client.test(header, ref datetime);
Above you see my Code to invoke the test Method. But I alway get the exception that the Server Certificate is probably not configured correctly with HTTP.SYS. Another Reason is a mismatch from Client and Server.
Can you help me with this issue? Have I set up the proxy classes correctly?
Many thanks in advance!
Regards Lars

Related

Error comsuming WCF service metadata?

We have a WCF webservice selfhosted in a windows service application.
It works fine to generate and call a simple method from both a .NET winform application and SoapUI(after changin to correct IP and set authentication header).
The problem is that when trying to add the WSDL to a BizTalk we get "Error consuming WCF service metadata. Object reference not set to an instance of an object". and nothing more.
I have search internet and there is some that have hade the same problem and they are talking about namespace problems. I have checked the generated .NET winform proxy but there is no warnings or anything that might suggest problems with namespaces? I notice in the WSDL that some namespaces tags do only have a "" value but not sure if that might be a problem.
Is there any way to get more information from Biztalk about where the error might be in this massive WSDL?
When browsing the WSDL from another computer it will use localhost(instead of the IP och DNS) so I have to use WSDL singelfile to genereate the proxy and I have to manually change the URL to the specific IP in the client to get it working. This should however not be the problem.
Here is how the service is started :
_serviceHost = new ServiceHost(typeof(T), new Uri(baseEndpoint.Address));
ServiceThrottlingBehavior throttleBehavior = new ServiceThrottlingBehavior
{
MaxConcurrentCalls = 200,
MaxConcurrentInstances = 2147483647,
MaxConcurrentSessions = 2000,
};
_serviceHost.Description.Behaviors.Add(throttleBehavior);
_serviceHost.Description.Behaviors.Add(smb.HttpGetEnabled = true);
foreach (var endpointDescription in _additionalServiceEndpoints)
{
var endpoint = new ServiceEndpoint(ContractDescription, endpointDescription.Binding, new EndpointAddress(endpointDescription.Address));
_endpointBehaviors.ForEach(c => endpoint.EndpointBehaviors.Add(c));
_serviceHost.AddServiceEndpoint(endpoint);
}
_serviceBehaviors.ForEach(c => _serviceHost.Description.Behaviors.Add(c));
ServiceAuthorizationBehavior serviceAuthorizationBehavior = _serviceHost.Description.Behaviors.Find<ServiceAuthorizationBehavior>();
if (serviceAuthorizationBehavior == null)
{
_serviceHost.Description.Behaviors.Add(new ServiceAuthorizationBehavior());
}
if (_authorizationPolicies.Count > 0)
{
serviceAuthorizationBehavior.ExternalAuthorizationPolicies = new ReadOnlyCollection<IAuthorizationPolicy>(_authorizationPolicies.ToArray());
serviceAuthorizationBehavior.PrincipalPermissionMode = PrincipalPermissionMode.Custom;
serviceAuthorizationBehavior.ServiceAuthorizationManager = new CustomServiceAuthorizationManager();
}
((ServiceBehaviorAttribute)_serviceHost.Description.Behaviors[typeof(ServiceBehaviorAttribute)]).MaxItemsInObjectGraph = 2147483647;
((ServiceBehaviorAttribute)_serviceHost.Description.Behaviors[typeof(ServiceBehaviorAttribute)]).IncludeExceptionDetailInFaults = true;
_serviceHost.Open();
Have you tried the solution which is described in this forum thread: https://social.msdn.microsoft.com/Forums/en-US/19105b96-5ec4-40f1-972b-2e04f889061f/biztalk-2010-error-consuming-wcf-service-metadata-object-reference-not-set-to-an-instance-of-an?forum=biztalkgeneral
It points to a blog post located here: https://blogs.msdn.microsoft.com/kerreybpi/2009/02/05/biztalk-error-wcf-service-consuming-wizard/
The solution might be (from the link above):
1, Generate WSDL and XSD files by using svcutil tool
svcutil.exe /t:metadata http://yourservice
2, Verify nodes in WSDL file, make sure the node has a target namespace define. It doesn't matter what attribute value you use, maybe just looks like http://any.
3, Select Metadata Files(WSDL and XSD) as the source
4, Everything should be fine.
I just had the same error when trying to consume .svc?singleWsdl. When I consume as just .svc into the "Add Generated Items" wizard then it works.

C# signing Soap Header in windows phone 8.1

We have the need to call a server with Soap with signed timestamp header on a Windows 8.1 phone. We are using VS Community 2015 as our dev environment. The webservice site has provided us with certificate to sign with. No username/password is to be used.
We have tried to use the code generated from adding a Service Reference from the wsdl file but have not found how to sign the header. As we try to run the call we get an "InvalidOperationException" with text saying we need to supply username. If we then supply a random username/password in the ClientCredentials we get MessageSecurityException with text "An unsecured or incorrectly secured fault was received from the other party. See the inner FaultException for the fault code and detail."
Has anyone managed to use a certificate to sign a time stamped soap header on Windows 8.1 phone? Noticed that most pages on MSDN for soap clients are page not found.
After this we looked around for examples of signing soap request header in c#. In following what code examples do we have not found that the System.Security.Cryptography.XML package is not available. Does anyone know where XmlDsigC14NTransform was moved or what a replacement would be for getting the DigestValue for the timestamp in the soap header?
Bottom line question on this would be does anyone have example of how to perform a soap request with a timestamped soap header that works on windows 8.1 phone?
Following is what we have tried. Names and addresses etc changed
SoapWS.myRequest req = new SoapWS.myRequest();
// setup the request fields
CustomBinding binding = new CustomBinding();
binding.Namespace = "urn:<the name space>";
binding.Name = "<name of binding>";
TransportSecurityBindingElement securityElement = new TransportSecurityBindingElement();
securityElement.IncludeTimestamp = true;
X509Certificate cert = new X509Certificate(<from loaded bytes>);
binding.Elements.Add(new TextMessageEncodingBindingElement(MessageVersion.Soap11, System.Text.Encoding.UTF8));
binding.Elements.Add(securityElement);
binding.Elements.Add(new HttpsTransportBindingElement());
SoapWS.myRequestClient client = new SoapWS.myRequestClient(
binding,
addr);
//client.ClientCredentials.UserName.UserName = "admin";
//client.ClientCredentials.UserName.Password = "admin";
using (new OperationContextScope(client.InnerChannel))
{
// Add a SOAP Header to an outgoing request
MessageHeader aMessageHeader = MessageHeader.CreateHeader("Security", binding.Namespace, cert);
OperationContext.Current.OutgoingMessageHeaders.Add(aMessageHeader);
}
client.myRequestCompleted += Client_completed;
client.myRequestSessionAsync(req);

Connecting to SAP Web Service from C# .NET application

I've written a Windows Application to test a connection to a clients SAP web services. The web service call requires X509 certificate security.
After reading various articles on the internet I've come up with three ways to attach the X509 certificate to the web service call. Unfortunately all of these attempts return a '401 Unauthorised Access'. However, I can connect to the web service via the URL in IE.
Does anybody have any sugestions as to what I may be doing wrong? I am using WSE 3.0 and the three methods I am using to attach the certificate are as follows:-
Certificate
X509Certificate2 oCert = GetSecurityCertificate(oCertificate);
svc.ClientCertificates.Add(oCert);
Token
X509SecurityToken oToken = GetSecurityToken(oCertificate);
svc.RequestSoapContext.Security.Tokens.Add(oToken);
Policy
SAPX509Assertion sapX509Assertion = new SAPX509Assertion(oCertificate, oStoreLocation, oStoreName, oFindType);
svc.SetPolicy(sapX509Assertion.Policy());
GetSecurityToken() and GetSecuirtyCertificate both search the certificate store. The SAPX509Assertion does this:-
public SAPX509Assertion(String certSubject, StoreLocation oStoreLocation, StoreName oStoreName, X509FindType oFindType)
{
ClientX509TokenProvider = new X509TokenProvider(oStoreLocation,
oStoreName, certSubject, oFindType);
ServiceX509TokenProvider = new X509TokenProvider(oStoreLocation,
oStoreName, certSubject, oFindType);
Protection.Request.EncryptBody = false;
Protection.Response.EncryptBody = false;
}
Update
OK, I have a WCF call now in place. I couldn't use the BasicHttpBinding method shown by Eugarps as it complained that I was connecting to a https address and expected http...which made sense. The code I now have is:-
var binding = new WSHttpBinding();
binding.MaxReceivedMessageSize = int.MaxValue;
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows;
binding.Security.Mode = SecurityMode.Transport;
WCFConnection.CreateAbsenceWSlow.ZWSDHTM_GB_AMS_CREATEABS_lowClient client;
CreateAbsenceWSlow.ZfhhrGbbapiZgeeamsCreateabsResponse response;
CreateAbsenceWSlow.ZfhhrGbbapiZgeeamsCreateabs data;
//Assign address
var address = new EndpointAddress(sUrl);
//Create service client
client = new CreateAbsenceWSlow.ZWSDHTM_GB_AMS_CREATEABS_lowClient(binding, address);
//Assign credentials
client.ClientCredentials.UserName.UserName = sUserName;
client.ClientCredentials.UserName.Password = sPassword;
response = new CreateAbsenceWSlow.ZfhhrGbbapiZgeeamsCreateabsResponse();
data = new WCFConnection.CreateAbsenceWSlow.ZfhhrGbbapiZgeeamsCreateabs();
response = client.ZfhhrGbbapiZgeeamsCreateabs(data);
It's still failing to connect to the SAP web service. The error I am receiving is "The HTTP request is unauthorized with client authentication scheme 'Negotiate'". I've also tried using
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;
which returned a similar error.
Does anybody have any further suggestions or ideas of where I am going wrong?
Now, this is all coming from my own experience so some of it may be wrong, but here's how I understand the process (I received no documentation and my company had no experience in calling SAP before I began doing it).
SAP WS calls are only supported by WCF BasicHttpBinding, and as far as I can tell, only using plain-text credentials. This means you will want to use IPSec or HTTPS if you need to make your communication private (outside intranet, or sensitive data within intranet). Our SAP server does not have HTTPS configured, but we use VPN with IPSec for external communication. Important to note is that, by default, SAP GUI also does not make communication private. In this situation, you are being no less secure by using the method detailed below than the business user down the hall who is looking up sensitive data in GUI 7.1. Here's how I connect to our SAP server internally:
//Create binding
//Note, this is not secure but it's not up to us to decide. This should only ever be run within
//the VPN or Intranet where IPSec is active. If SAP is ever directly from outside the network,
//credentials and messages will not be private.
var binding = new BasicHttpBinding();
binding.MaxReceivedMessageSize = int.MaxValue;
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;
binding.Security.Mode = BasicHttpSecurityMode.TransportCredentialOnly;
//Assign address
var address = new EndpointAddress(Host);
//Create service client
var client = new SAP_RFC_READ_TABLE.RFC_READ_TABLEPortTypeClient(binding, address);
//Assign credentials
client.ClientCredentials.UserName.UserName = User;
client.ClientCredentials.UserName.Password = Password;
As far as I have been able to determine, message-level security is not supported, and bindings other than basicHttpBinding (SOAP 1.1) are not supported.
As I said, this is all from experience and not from training, so if anybody can add something through comments, please do so.
I've faced the same problem and it seems I've found the sollution here: http://ddkonline.blogspot.com/2009/08/calling-sap-pi-web-service-using-wcf.html.
CustomBinding binding = new CustomBinding();
binding.Elements.Add(new TextMessageEncodingBindingElement(MessageVersion.Soap11, Encoding.UTF8));
HttpsTransportBindingElement transport = new HttpsTransportBindingElement();
transport.AuthenticationScheme = AuthenticationSchemes.Basic;
//transport.ProxyAuthenticationScheme = AuthenticationSchemes.Basic;
transport.Realm = "XISOAPApps";
binding.Elements.Add(transport);
var address = new EndpointAddress("https://foooo");
........ create client proxy class
service.ClientCredentials.UserName.UserName = "<login>";
service.ClientCredentials.UserName.Password = "<password>";
Unfortunatelly I'm not able to use WCF in my application, I have to stick with .NET 2.0 and WSE 3.0, and I wounder if anybody was able to find sollution to that?
After all this time, the client has finally obtained someone to deal with the issue from their SAP end of things. Turns out the WSDL files we were supplied were incorrect and the certification had been done wrong. I reran my code with the new WSDL files and it worked first time.
Does your certificate happen to be mapped to a valid user in your user store?

WCF NetTcpBinding - from Microsoft tutorial - getting timeout

I built a project as descripted in this URL:
http://msdn.microsoft.com/en-us/library/ms734784.aspx
I used the app.config version. But using the code-Version does not change anything (the timeout-error still occurs).
To create the ServiceHost I used the following code:
this.serviceHost = new ServiceHost(typeof(Calculator));
// Open the ServiceHostBase to create listeners and start
// listening for messages.
this.serviceHost.Open();
On the client side I used the following code:
ChannelFactory<ICalculator> factory = new ChannelFactory<ICalculator>("netTcp_ICalculator");
ICalculator communicationChannel = this.factory.CreateChannel();
string test = communicationChannel.GetData(5);
On the last line the program waits one minute, then I get a timeout:
This request operation sent to net.tcp://localhost:8008/Calculator did not
receive a reply within the configured timeout (00:01:00).
The time allotted to this operation may have been a portion
of a longer timeout. This may be because the service is still
processing the operation or because the service was unable to
send a reply message. Please consider increasing the operation
timeout (by casting the channel/proxy to IContextChannel and
setting the OperationTimeout property) and ensure that the service
is able to connect to the client.
The class Calculator and the interface exist. Besides this timeout I get no other error. I set a breakpoint at the GetData method, but the breakpoint was not hit.
I have tried to change the portnumber used for the client from 8008 to 8009, but let the endpoint for the server at 8008. I wanted to test if the client tries to reach the server. Then I get the error that the other side is not answering (EndpointNotFoundException).
When changing the client port back to 8008 I get the Timeout error again.
Is there anything wrong with my code?
How can I ensure that the server can reach the client?
Client and server are in the same test application.
Thank you for your help!
EDIT:
I have now deleted the app.config settings. And tried to build the server and client by using the sourcecode. To build the server was no problem. But building the client is a problem.
There is no way to call:
CalculatorClient cc = new CalculatorClient(myBinding, myEndpointAddress);
The compiler does not know CalculatorClient.
Can I use the following instead?
NetTcpBinding myBinding = new NetTcpBinding();
myBinding.Security.Mode = SecurityMode.None;
// Create the address string, or get it from configuration.
string tcpUri = "net.tcp://localhost:8008/Calculator";
// Create an endpoint address with the address.
EndpointAddress myEndpointAddress = new EndpointAddress(tcpUri);
ChannelFactory<ICalculator> factory = new ChannelFactory<ICalculator>(myBinding, myEndpointAddress);
factory.Open();
ICalculator communicationChannel = this.factory.CreateChannel();
string test = communicationChannel.GetData(5);
I get again an exception at the last line :(
SOLVED:
Ok, the problem is solved. I needed to call the WCF host initialization via an own thread:
hostThread = new Thread(this.createService);
hostThread.Start();
Now everything works fine!
Thanks for all your help!
You are not adding any endpoints to the service.
You did not include the part of the example code that adds the service endpoint:
Uri tcpUri = new Uri("net.tcp://localhost:8008/Calculator");
// Create the ServiceHost.
ServiceHost sh = new ServiceHost(typeof(Calculator), tcpUri);
// Create a binding that uses TCP and set the security mode to none.
NetTcpBinding b = new NetTcpBinding();
b.Security.Mode = SecurityMode.None;
// Add an endpoint to the service.
sh.AddServiceEndpoint(typeof(ICalculator), b, "");
// Open the service and wait for calls.
sh.Open();
Edit: Same goes for your client. You have to specify an endpoint addresses
// Create a channel factory.
NetTcpBinding b = new NetTcpBinding();
b.Security.Mode = SecurityMode.None;
Uri tcpUri = new Uri("net.tcp://localhost:8008/Calculator");
ChannelFactory<ICalculator> myChannelFactory = new ChannelFactory<ICalculator>(b,new EndpointAddress(tcpUri));
// Create a channel.
ICalculator calculator = myChannelFactory.CreateChannel();
Edit2: I can't currently test this code... Will give it a try tomorrow morning.
Are you using Windows 7?
If so, you likely need to run Visual Studio as an Administrator. UAC will not let you create the service endpoint unless you are a running as an administrator.

Calling webservice in C# using SSL - '(401) Unauthorized'

I'm calling a method on a web service from behind a proxy server using the following code:
myWebService.TestWebService webservice = new myWebService.TestWebService();
webservice.Url = "http://test.com/webservice?wsdl";
WebProxy proxy = new WebProxy("1.2.3.4", 8080);
proxy.Credentials = new NetworkCredential("username", "password");
webservice.Proxy = proxy;
string response = webservice.TestWebMethod();
This works fine when using HTTP, I get the response I'm expecting in the 'response' string.
However - if I change the URL to HTTPS then I get a (401) Unauthorized response.
If I put the URL into my browser it works fine using HTTP or HTTPS.
I've added code to handle the SSL certificate validation by creating a System.Net.ServicePointManager.ServerCertificateValidationCallback delegate but the code never gets this far. The request is rejected before it validates the certificate or so it seems.
Any help is really appreciated...
Do you need credentials to navigate to the SSL url?
If so you need the web service credentials set.
Have you tried adding a web reference in Visual Studio using the SSL url?
If you can't add web reference through Visual Studio then the code is not going to work either.
Can you make sure that the last thing that you set is the proxy (e.g. change the url before you set the proxy)?
There is a small chance that the proxy could be lost, this should be the very last thing to try
Here is an example using a client cert (which i'm sure you don't need) but might provide some insight & using credentials to a web service.
WebService.ManageOutboundDelivery oWS = new WebService.ManageOutboundDelivery();
if (My.Settings.HasClientCert == true) {
X509Certificate2 signedCert = new X509Certificate2(HttpContext.Current.Server.MapPath(My.Settings.ClientCertName), My.Settings.ClientCertPW);
oWS.ClientCertificates.Add(signedCert);
}
System.Net.CredentialCache oCred = new System.Net.CredentialCache();
Net.NetworkCredential netCred = new Net.NetworkCredential(My.Settings.WebServiceUID, My.Settings.WebServicePW);
oCred.Add(new Uri(oWS.Url), "Basic", netCred);
oWS.Credentials = oCred;
Have you also checked the SSL cert is valid - i'm guessing you would see this when you hit it through the browser but it could be causing a problem trying to hit it programmatically.

Categories

Resources