The HTTP request did not contain a valid SOAPAction header - web-services

I am invoking an opportunity service, but ending with the following Error.
SOAP Response:
<?xml version="1.0" encoding="UTF-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><soap:Fault><faultcode>soap:Client</faultcode><faultstring>Client</faultstring><detail><ErrorCode>SBL-ODU-01007</ErrorCode><ErrorMessage>The HTTP request did not contain a valid SOAPAction header
The value of the header was:
document/urn:crmondemand/ws/ecbs/opportunity/10/2004:OpportunityQueryPage</ErrorMessage></detail></soap:Fault></soap:Body></soap:Envelope>
I am using apache http client to invoke this service.
SOAP Request Msg:
<?xml version=\"1.0\" encoding=\"UTF-8\"?><soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:ns=\"urn:crmondemand/ws/ecbs/opportunity/10/2004\" xmlns:quer=\"urn:/crmondemand/xml/Opportunity/Query\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:wsse=\"http://schemas.xmlsoap.org/ws/2002/07/secext\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"> <soapenv:Header><wsse:Security><wsse:UsernameToken><wsse:Username>XXXXXX</wsse:Username><wsse:Password Type=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText\">XXXXXXX</wsse:Password></wsse:UsernameToken></wsse:Security></soapenv:Header><soapenv:Body><ns:OpportunityQueryPage_Input><quer:ListOfOpportunity pagesize=\"100\" startrownum=\"1\" recordcountneeded=\"5\"><quer:Opportunity searchspec=\"[Owner] LIKE '*'\"><quer:Description sortorder=\"ASCE\"></quer:Description><quer:AccountName sortorder=\"ASCE\"></quer:AccountName><quer:cActual_Booking_ValueTCV_Mn></quer:cActual_Booking_ValueTCV_Mn></quer:Opportunity></quer:ListOfOpportunity></ns:OpportunityQueryPage_Input></soapenv:Body></soapenv:Envelope>
My Invocation URL:
https://secure-ausomxapa.crmondemand.com/Services/Integration
I am not able to find exactly where is the error. Kindly Help to fix this issue.

Here is an example which works for activities:
soapAction: '"document/urn:crmondemand/ws/ecbs/activity/10/2004:ActivityQueryPage"',
data: '<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><ActivityQueryPage_Input xmlns="urn:crmondemand/ws/ecbs/activity/10/2004"><ListOfActivity pagesize="20" xmlns="urn:/crmondemand/xml/Activity/Query"><Activity searchspec= "[Id] = \''+myTextBox.val()+'\'"><Id></Id><Subject></Subject><Type></Type><Priority></Priority><Description></Description><CommentsAction></CommentsAction><OwnerFullName></OwnerFullName><DelegatedBy></DelegatedBy></Activity></ListOfActivity></ActivityQueryPage_Input></soap:Body></soap:Envelope>',
callback: function (data) {}

Related

Power Bi Soap Request

I have a web service which uses soap actions to retrieve data. How can I add such a request to use inside Power BI. I tied Get Data from Web, but it seems I only can add request headers but no body.
POST /subtarget/SERVICE.asmx HTTP/1.1
Host: website.com
Content-Type: text/xml; charset=utf-8
SOAPAction: "http://methods.org/GetProducts"
Content-Length: 559
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<GetProducts xmlns="http://tempuri.org/">
<username>name</username>
<password>pass</password>
<supplierId>313</supplierId>
</GetProducts>
</soap:Body>
</soap:Envelope>
You can add a body to Web.Contents as a second argument, using [Content = Body].
I have used http://dneonline.com/calculator.asmx to demonstrate, the request is quite simple, it will add two numbers.
Steps
Define your SOAP envelope inside your PowerQuery. Remove any unnecessary whitespaces, and transform single quotes " to double quotes "". Let's save this into a variable called SoapEnvelope.
Transform your SOAPEnvelope into binary using Text.ToBinary.
Construct the Web.Contents using Content with the the transformed SOAPEnvelope and the Header, in this case you only need #"Content-type" = 'text/xml'.
Wrap your Web.Contents into an XML content to display as Table.
let
SOAPEnvelope=
"<?xml version=""1.0"" encoding=""utf-8""?>
<soap:Envelope xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" xmlns:soap=""http://schemas.xmlsoap.org/soap/envelope/"">
<soap:Body><Add xmlns=""http://tempuri.org/"">
<intA>1</intA>
<intB>2</intB></Add>
</soap:Body>
</soap:Envelope>",
Source = Xml.Document(
Web.Contents(
"http://dneonline.com/calculator.asmx",
[Content = Text.ToBinary(SOAPEnvelope), Headers = [#"Content-Type" = "text/xml"]]
)
)
in
Source

How to send SOAP request via Postman

I'm trying to send a SOAP request via the Postman chrome extension. My request body looks like this in Postman:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://partnerapi.somewhere.com/">
<soapenv:Body>
<ns1:GetCustomers>
<GetCustomersRequest>
<APIKey>SECRET</APIKey>
<PartnerKey></PartnerKey>
<SearchText></SearchText>
<ItemsPerPage>50</ItemsPerPage>
<PageNumber>1</PageNumber>
<Fields></Fields>
<OrderBy></OrderBy>
</GetCustomersRequest>
</ns1:GetCustomers>
</soapenv:Body>
</soapenv:Envelope>
Edit:
Clicking the Generate Code button in Postman provides the following snippet:
POST /PartnerAPI.asmx HTTP/1.1
Host: localhost:3000
Content-Type: text/xml
SOAPAction: http://partnerapi.somewhere.com/GetCustomers
Cache-Control: no-cache
Postman-Token: 1af78251-9d36-0c94-d0e3-21f7e37ffc41
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://partnerapi.somewhere.com/">
<soapenv:Body>
<ns1:GetCustomers>
<GetCustomersRequest>
<APIKey>SECRET</APIKey>
<PartnerKey></PartnerKey>
<SearchText></SearchText>
<ItemsPerPage>50</ItemsPerPage>
<PageNumber>1</PageNumber>
<Fields></Fields>
<OrderBy></OrderBy>
</GetCustomersRequest>
</ns1:GetCustomers>
</soapenv:Body>
</soapenv:Envelope>
I have the web service running in Visual Studio and I have a breakpoint set in the web method which is being hit so the request is reaching the endpoint.
The web method signature looks like this:
[WebMethod]
public CustomersObject GetCustomers(RequestObjects.GetCustomersRequest GetCustomersRequest)
But the GetCustomersRequest parameter is always NULL.
The GetCustomersRequest class looks like this:
public class GetCustomersRequest {
public string APIKey;
public string PartnerKey;
public string SearchText;
public int ItemsPerPage = 50;
public int PageNumber = 1;
public string Fields;
public string OrderBy;
}
Any idea why?
It turned out to be quite straight forward in the end. All I did was browse to the web service, which then lists the endpoints available. Then clicked on the GetCustomers link. Which shows an example of the XML required. I then used that as the basis for the request body in Postman (You may notice that some of the namespaces are different from my original attempt).
Clicking the Generate Code button in Postman produces the following:
POST /PartnerAPI.asmx HTTP/1.1
Host: localhost:53355
Content-Type: text/xml; charset=utf-8
SOAPAction: http://partnerapi.somewhere.com/GetCustomers
Cache-Control: no-cache
Postman-Token: 914d2152-9063-ff57-91a0-e567714c2d44
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<GetCustomers xmlns="http://partnerapi.somewhere.com/">
<GetCustomersRequest>
<APIKey>SECRET</APIKey>
<SearchText></SearchText>
<ItemsPerPage>10</ItemsPerPage>
<PageNumber>1</PageNumber>
<Fields></Fields>
<OrderBy></OrderBy>
</GetCustomersRequest>
</GetCustomers>
</soap:Body>
</soap:Envelope>
Which successfully reaches the endpoint but this time the GetCustomersRequest parameter is populated correctly!

Calling multiple WCF and asmx web services dynamically without generating proxy or using WSDL

We connect with multiple (20-30) third-party web services within our C# Batch Application. We are attempting to find the best way to call these web services dynamically (without generating proxy or using wsdl). All the third party agencies endpoints or URL's will be configured in database table. Client app will check the URL at run-time and make a service call. We are not worried about async calls it’s all synchronized process.
SQL Table : Client-configuration
Client URL Method IsActive
A http://serverhost/ClientA/Service1.svc Submit 1
B http://serverhost/ClientB/Service2.asmx Submit 1
The only issue is we are not sure about the third party service implementation is WCF or asmx. I have read few articles online to use HttpWebRequest to call web services dynamically (without generating proxies/wsdl.)
Is this the best way to implement this or any concerns I need to think of?
Please see below ex:
public static void CallWebService(string xml)
{
var _Url = "http://serverhost/ClientA/Service1.svc";
var _action = "http://serverhost/ClientA/Service1.svc/Submit";
try
{
ASCIIEncoding encoder = new ASCIIEncoding();
byte[] data = encoder.GetBytes(xml);
XmlDocument soapEnvelopeXml = CreateSoapEnvelope(xml);
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(_Url);
webRequest.Headers.Add("SOAPAction", _action);
webRequest.ContentType = "text/xml;charset=\"utf-8\"";
webRequest.ContentLength = data.Length;
webRequest.Accept = "text/xml";
webRequest.Method = "POST";
Stream webStream = webRequest.GetRequestStream();
webStream.Write(data, 0, data.Length);
webStream.Close();
WebResponse response = webRequest.GetResponse();
Stream responseStream = response.GetResponseStream();
using (StreamReader sr = new StreamReader(responseStream))
{
string s = sr.ReadToEnd();
}
}
catch (Exception ex)
{
responseStream = ex.Response.GetResponseStream();
}
}
Here is the details shared by one of the client.
http://setup.localhost.com/ClientA/Service1.asmx
Operation : Submit
SOAP 1.1
The following is a sample SOAP 1.1 request and response. The placeholders shown need to be
replaced with actual values.
POST /ClientA/Service1.asmx HTTP/1.1
Host: setup.localhost.com
Content-Type: text/xml; charset=utf-8
Content-Length: length
SOAPAction: "http://setup.localhost.com/Submit"
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<Submit xmlns="http://setup.localhost.com/">
<eCitXML>string</eCitXML>
<eCitPdf>base64Binary</eCitPdf>
<eCitKey>string</eCitKey>
</Submit>
</soap:Body>
</soap:Envelope>
HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: length
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<SubmitResponse xmlns="http://setup.localhost.com/">
<SubmitResult>string</SubmitResult>
</SubmitResponse>
</soap:Body>
</soap:Envelope>
SOAP 1.2
The following is a sample SOAP 1.2 request and response. The placeholders shown need to be
replaced with actual values.
POST /ClientA/Service1.asmx HTTP/1.1
Host: setup.localhost.com
Content-Type: application/soap+xml; charset=utf-8
Content-Length: length
<?xml version="1.0" encoding="utf-8"?>
<soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-
envelope">
<soap12:Body>
<Submit xmlns="http://setup.localhost.com/">
<eCitXML>string</eCitXML>
<eCitPdf>base64Binary</eCitPdf>
<eCitKey>string</eCitKey>
</Submit>
</soap12:Body>
</soap12:Envelope>
HTTP/1.1 200 OK
Content-Type: application/soap+xml; charset=utf-8
Content-Length: length
<?xml version="1.0" encoding="utf-8"?>
<soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-
envelope">
<soap12:Body>
<SubmitResponse xmlns="http://setup.localhost.com/">
<SubmitResult>string</SubmitResult>
</SubmitResponse>
</soap12:Body>
</soap12:Envelope>
I think your question could be rephrased as
Is there a generic method to call any SOAP 1.1 or 1.2 web service operation without prior knowledge of the service operation except for the SOAP action and URL?
I'm assuming that all the third party web services expose a common operation which accepts and returns the same types.
If this is the case then providing you model the service operation contract correctly you could use ChannelFactory to call all the services.
Calling WCF services is straightforward in this manner, but to call asmx services you'd need to do a bit more work. So your client code would need to know if the service was asmx or wcf, and moreover, if wcf, whether the service is soap 1.1 or 1.2.
I must say I'm struggling to understand what advantage you will have once you have achieved this. I can see the value if you owned all the 20+ services you were calling, but this clearly is not the case.
Granted, you won't have a ton of nasty generated service reference code, but the whole point of WSDL is it allows for machine generated service contracts. If the third party services make any breaking changes you'll need to manually synchronize these inside your client code, rather than just regenerating the client.

ASMX webserive not recieving parameters from classic ASP soap request.

I am attempting to wrap a newer .net ASMX webservice so that it can be used by an older classic asp application. To do this I found some code to send the soap requests. However in my testing it seems that none of my parameters are reaching the server.
The Server Test Code
<WebMethod()> _
Public Function Ping1(str As String)
If str <> "" Then
Return str
Else
Return "False"
End If
End Function
The xml being sent:
<?xml version="1.0" encoding="utf-8"?>
<soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
<soap12:Body>
<Ping1 xmlns="http://tempuri.org">
<str>asdf</str>
</Ping1>
</soap12:Body>
</soap12:Envelope>
The page keeps returning "False" but as far as I can tell, this should be the right format to send parameters. Any help would be appreciated.
As demonstrated in this other question you should set proper headers when consuming the service:
oXmlHTTP.setRequestHeader "Content-Type", "application/soap+xml; charset=utf-8"
oXmlHTTP.setRequestHeader "SOAPAction", "http://ourNameSpace/Ping1"
Note that you can't use tempuri.org namespace, you have to also set your own namespace.

How do I access SourceGear Web services using SOAP::Lite?

For some reason SourceGear provide an undocumented Web service on their installations. They actually ask developers to use the API instead because the Web service is kinda messy, but this is a problem in my case because I cannot use this API on a Perl environment, so their solution for my specific case is to use the Web service.
This shouldn't be a problem. Using SOAP::Lite I have connected to several Web services in the past in the same way. But the lack of documentation is a major chaos if you don't know where the SOAP calls can be made. I only have an XML to decipher where to and how to make these calls. It would be great if a real SOAP genius could help me out in this.
This is an example of the login call and the expected response:
Request
POST /fortress/dragnetwebservice.asmx HTTP/1.1
Host: velecloudserver
Content-Type: text/xml; charset=utf-8
Content-Length: length
SOAPAction: "http://www.sourcegear.com/schemas/dragnet/LoginPlainText"
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<LoginPlainText xmlns="http://www.sourcegear.com/schemas/dragnet">
<strLogin>string</strLogin>
<strPassword>string</strPassword>
</LoginPlainText>
</soap:Body>
</soap:Envelope>
Response
HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: length
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<LoginPlainTextResponse xmlns="http://www.sourcegear.com/schemas/dragnet">
<LoginPlainTextResult>int</LoginPlainTextResult>
<strAuthTicket>string</strAuthTicket>
</LoginPlainTextResponse>
</soap:Body>
</soap:Envelope>
I'm looking for a way to be able to assemble this somehow. This is my Perl example:
my $soap = SOAP::Lite -> uri ('http://velecloudserver/fortress/dragnetwebservice.asmx') -> proxy('http://velecloudserver/fortress/dragnetwebservice.asmx/LoginPlainText');
my $som = $soap->call('LoginPlainText', SOAP::Data->name('LoginPlainText')->value(
\SOAP::Data->value([
SOAP::Data->name('strLogin')->value( 'admin' ),
SOAP::Data->name('strPassword')->value('Adm1234'),
]))
);
Any tip would be appreciated.
Start by pointing wget/curl/lwp/etc. at http://velecloudserver/fortress/dragnetwebservice.asmx?WSDL
and see if you get a WSDL file back.
If you do, then compare it to the four types listed in the SOAP::Lite POD.
Your Request example looks like the Docment/Literal form, so you might end up writing something like this:
use SOAP::Lite;
my $soap = SOAP::Lite->new( file => 'http://velecloudserver/fortress/dragnetwebservice.asmx?WSDL');
$soap->on_action( sub { "urn:dragnetservice#LoginPlainText" });
$soap->autotype(0);
$soap->default_ns('urn:LoginPlainText');
my $som = $soap->call("LoginPlainText",
SOAP::Data->name('strLogin')->value( 'admin' ),
SOAP::Data->name('strPassword')->value('Adm1234'),
);
die $som->fault->{ faultstring } if ($som->fault);
print $som->result, "\n";
If you don't get WSDL back, I'd try replacing the constructor call with:
my $soap = SOAP::Lite->new( proxy => 'http://velecloudserver/fortress/dragnetwebservice.asmx');
The last time I worked with SOAP::Lite, I wrote a short program similar to the one above, and I ran it under the debugger. Before I executed the $soap->call() line, I peeked at the guts of the $soap object and looked at the request payload to see if the XML matched some working XML that I had by using the soapUI.org java client.
I had to read the POD a couple of times, and I dug into the source to figure our how some of the methods like default_ns() affected the generated XML. Once I did that, it all made a lot more sense.
Note: SOAP::Lite likes to die() when it fails. Wrap your calls in an eval{} for production use.