How to use SOAP Request within AJAX call - ajax

This is my AJAX Application where i need to contact my Webservice running in server .
function sendRequest(method, url)
{
method == 'post';
{
http.open(method,url,true);
http.onreadystatechange = handleResponse;
http.send(null);
}
}
This is the SOAP Request which i picked up from the SOAP UI , which was working fine
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ser="http://service.bayer.tata.com/" xmlns:tkw="http://tata.com/bayer" xmlns:chim="http://tata.com/chimera">
<soapenv:Header/>
<soapenv:Body>
<ser:strategy>
<!--Optional:-->
<request>
<xmlMessage>
<![CDATA[<test>or like this</test>]]>
</xmlMessage>
</request>
</ser:strategy>
</soapenv:Body>
</soapenv:Envelope>
Please tell me how can i use use this SOAP XML message within the sendRequest function .
I am using only plain Java Script AJAX ( Nothing like Jquery , DOJO , or any )

I think this Post can help you. But most of web servers allows you to invoke webservices using plain HTTP Post (without SOAP format in the body request) if the request doesn't need SOAP headers or other weird things.
An example in .NET and plain javaScript:
.NET web service
<System.Web.Services.WebService(Namespace:="http://JuntaEx/Agricultura/SegurInfo/GestorFirmaExterno/")> _
<System.Web.Services.WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _
<ToolboxItem(False)> _
Public Class GestorFirmaExterno
Inherits System.Web.Services.WebService
<WebMethod(Description:="Retorna los documentos originales asociados a un identificador de firma pasado como parámetro.")> _
Public Function ObtenerDocumentoOriginal(ByVal idFirma As String) As DocumentoED()
//code
End Function
End Class
web.config:
<webServices>
<protocols>
<add name="HttpSoap"/>
<add name="HttpPost"/> <!-- Allows plain HTTP Post -->
<add name="HttpSoap12"/>
<!-- Documentation enables the documentation/test pages -->
<add name="Documentation"/>
</protocols>
</webServices>
JavaScript request:
function crearRequest(url) {
if (window.XMLHttpRequest) {
peticion_http = new XMLHttpRequest();
}
else if (window.ActiveXObject) {
peticion_http = new ActiveXObject('Microsoft.XMLHTTP');
}
peticion_http.open('POST', url, true); //sync
peticion_http.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
return peticion_http;
}
peticion_http = crearRequest('http://localhost/wspuenteFirma/serviciopuente.asmx/ObtenerDocumentoOriginal');
peticion_http.onreadystatechange = obtenerDocHandler;
var query_string = 'IdFirma=' + encodeURIComponent(docId);
peticion_http.setRequestHeader('Content-Length', query_string.length);
peticion_http.send(query_string);
You send this request to the server:
POST /wsGestorFirmaExterno/GestorFirmaExterno.asmx/ObtenerDocumentoOriginal HTTP/1.1
Host: localhost
Content-Type: application/x-www-form-urlencoded
Content-Length: length
idFirma=string
and recive this response from the server:
HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: length
<?xml version="1.0" encoding="utf-8"?>
<ArrayOfDocumentoED xmlns="http://JuntaEx/Agricultura/SegurInfo/GestorFirmaExterno/">
<DocumentoED>
<hash>string</hash>
</DocumentoED>
<DocumentoED>
<hash>string</hash>
</DocumentoED>
</ArrayOfDocumentoED>
Parse it with javascript to obtain the info you need.
PS: You can configure the server and the browser request to send and recive JSON data instead of XML.
I hope it's helps.

Related

CORS 405 (Method Not Allowed)

i intend to send a cross-domain request to a soap web service using Ajax
The url of the web service is: http://example1.asmx?op=GetVOD
My code:
var url = 'http://example1.asmx?op=GetVOD';
var xhr = new XMLHttpRequest();
var strRequest = "<?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>" +
"<getVODTypeList xmlns='http://tv21.com/' />" +
"</soap:Body>" +
"</soap:Envelope>"
xhr.open('POST', url, true);
xhr.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
xhr.setRequestHeader("SOAPAction", "http://tv21.com/getVOD");
xhr.send(strRequest);
On the IIS 7 server side, i've already add these lines to the file web.config
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Methods" value="GET,PUT,POST,DELETE,OPTIONS" />
<add name="Access-Control-Allow-Headers" value="Content-Type" />
when i run the client code on Chrome, i have an 405 error:
http://example1.asmx?op=GetVOD 405 (Method Not Allowed)
http://example1.asmx?op=GetVOD Invalid HTTP status code 405
Does anyone know how to solve this ?
Thank in advance
Sounds like Web DAV is getting in the way. Here's the config to remove it:
http://brockallen.com/2012/10/18/cors-iis-and-webdav/

Bing Translation Api access via SOAP interface from Ruby

I'm trying to use Bing Translator SOAP API (due to in HTTP API I'm getting 414 "Request too long" for not so big requests due to UTF-8 serialization).
So, I'm playing with bing_translator gem source trying to switch it from HTTP inerface to SOAP one using Savon SOAP toolkit.
My workflow as follows (access token getting function not shown):
WSDL_URI = 'http://api.microsofttranslator.com/V2/soap.svc?wsdl'
get_access_token
client = Savon.client(wsdl: WSDL_URI, headers: {'Authorization' => "Bearer #{#access_token['access_token']}"})
params = {
'from' => 'ru',
'to' => 'en',
'text' => 'Это текст для перевода',
'category' => 'general',
'contentType' => 'text/plain'
}
result = client.call(:translate, message: params)
Then SOAP request executes:
SOAP request: http://api.microsofttranslator.com/V2/soap.svc
Authorization: Bearer http%3a%2f%2fschemas.xmlsoap.org%2fws%2f2005%2f05%2fidentity%2fclaims%2fnameidentifier=invest_amurobl_ru&http%3a%2f%2fschemas.microsoft.com%2faccesscontrolservice%2f2010%2f07%2fclaims%2fidentityprovider=https%3a%2f%2fdatamarket.accesscontrol.windows.net%2f&Audience=http%3a%2f%2fapi.microsofttranslator.com&ExpiresOn=1381128612&Issuer=https%3a%2f%2fdatamarket.accesscontrol.windows.net%2f&HMACSHA256=Mw41PMMgw2n6ZVaGRXtwfR0vwMJUyIMltIyd9pa9MqA%3d
SOAPAction: "http://api.microsofttranslator.com/V2/LanguageService/Translate"
Content-Type: text/xml;charset=UTF-8
Content-Length: 454
<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:wsdl="http://tempuri.org/" xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
<env:Body>
<wsdl:Translate>
<to>en</to>
<text>Это текст для перевода</text>
<category>general</category>
<contentType>text/html</contentType>
<from>ru</from>
</wsdl:Translate>
</env:Body>
</env:Envelope>
And I'm getting error 500: Unhandled Service Exception
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<s:Fault>
<faultcode>s:Client</faultcode>
<faultstring xml:lang="en-US">Unhandled Service Exception</faultstring>
<detail>
<int xmlns="http://schemas.microsoft.com/2003/10/Serialization/">1</int>
</detail>
</s:Fault>
</s:Body>
</s:Envelope>
What's may be wrong? Can anyone who already using Bing Translator SOAP API to diff my soap-messages with yourself? Any advices to how to troubleshoot this.
Thanks for attention.
EDIT:
I've checked API with SoapUI, as #SteffenRoller advices and it works. Here is XML generated by SoapUI (values are inserted by hand):
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:v2="http://api.microsofttranslator.com/V2">
<soapenv:Header/>
<soapenv:Body>
<v2:Translate>
<!--Optional:-->
<v2:text>Текст, который я хочу перевести</v2:text>
<!--Optional:-->
<v2:from>ru</v2:from>
<!--Optional:-->
<v2:to>en</v2:to>
<!--Optional:-->
<v2:contentType>text/plain</v2:contentType>
<!--Optional:-->
<v2:category>general</v2:category>
</v2:Translate>
</soapenv:Body>
</soapenv:Envelope>
As you can see the only difference is that all the tags inside a <Body> are in the v2 namespace. In the XML, generated by Savon this namespace isn't present at all.
So, now question is: How to instruct Savon to use correct namespace for tags inside the message body?
Although, I think, this is a Savon bug, I'll file it to developers, as SoapUI have generated correct XML by the same WSDL, and Savon doesn't.
Okay. This is a known bug: Savon issue #340. It's related to composite WSDL files and won't bi fixed in current major release :-(
So, in our case we need to tell Savon, what is our namespace is, what is it's name (just to align it with WSDL) and prepend each tag's name with this namespace.
The correct code looks like this:
require 'savon'
access_token = "http%3a%2f%2fschemas.xmlsoap.org%2fws...CA9TEs%3d"
client = Savon.client(
wsdl: 'http://api.microsofttranslator.com/V2/soap.svc?wsdl',
namespace: 'http://api.microsofttranslator.com/V2',
namespace_identifier: :v2,
headers: {'Authorization' => "Bearer #{access_token}"},
)
params = {
'v2:text' => 'Это текст для перевода',
'v2:from' => 'ru',
'v2:to' => 'en',
'v2:contentType' => 'text/plain',
'v2:category' => 'general',
}
result = client.call(:translate, message: params)
puts result.body[:translate_response][:translate_result]
Any advices and corrections are welcome. Thanks.

Savon - SOAP - ruby - 400 Bad Request

I'm trying to use Savon to make a SOAP request with Ruby, but I'm receiving a 400 Bad Request response from the server.
This is the request I'm trying to make (according to soapUI):
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:apis="http://www.csisoftwareusa.com/ApiService">
<soap:Header/>
<soap:Body>
<apis:AuthenticateConsumer>
<!--Optional:-->
<apis:consumerName>?</apis:consumerName>
<!--Optional:-->
<apis:consumerPassword>?</apis:consumerPassword>
</apis:AuthenticateConsumer>
</soap:Body>
</soap:Envelope>
Here is the request that I make with Ruby; it returns a 400 Bad Request error:
<SOAP-ENV:Envelope>
<SOAP-ENV:Body>
<ins0:AuthenticateConsumer>
<ins0:consumerName>?</ins0:consumerName>
<ins0:consumerPassword>?</ins0:consumerPassword>
</ins0:AuthenticateConsumer>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Http Headers: SOAPAction: "http://www.csisoftwareusa.com/ApiService/AuthenticateConsumer", Content-Type: text/xml;charset=UTF-8, Content-Length: 504
Here is the request that I was able to make with Python. THIS request succeeds:
<SOAP-ENV:Envelope>
<SOAP-ENV:Header/>
<ns0:Body>
<ns1:AuthenticateConsumer>
<ns1:consumerName>?</ns1:consumerName>
<ns1:consumerPassword>?</ns1:consumerPassword>
</ns1:AuthenticateConsumer>
</ns0:Body>
</SOAP-ENV:Envelope>
Http headers: {'SOAPAction': u'"http://www.csisoftwareusa.com/ApiService/AuthenticateConsumer"', 'Content-Type': 'text/xml; charset=utf-8'}
I need to integrate calls to this API into a Rails application, so doing it in Python isn't a valid solution.
I'm wondering if anyone can see what I'm missing. Is the empty <SOAP-ENV:Header /> tag the issue, and if so, how can I add that to the Savon request?
Thanks,
Stuart
In my case, I had repeated namespaces, so I was getting 400 Bad Request.
My code:
require 'savon'
namespaces = {
"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",
}
client = Savon.client(
...
:namespace => namespaces
}
I removed the :namespace option and the error was gone.
How did I find the error?
Use build_request instead of call and print the request body:
client.build_request(:search, message: {...})
puts request.body
I took the request body and pasted it into SoapUI, then I made changes one by one until the request was successful.
The issue here is with my http headers: Because the url has spaces in it, the url has to be encoded. However, I have to encode it before passing it to Savon, which then encodes it again - this double-encoded url fails. See: https://stackoverflow.com/questions/14482251/ruby-savon-soap-request-double-escapes-spaces-in-url
Thanks,
Stuart

Ruby: Savon SOAP Requests receives 400 and 415 errors

I am trying to make a SOAP request using the ruby library Savon.
I am using the following code:
require "savon"
Savon.configure do |config|
config.soap_version = 2 # use SOAP 1.2
config.raise_errors = false
end
wsdl_logon = Savon::Client.new do
wsdl.document = "https://api.affili.net/V2.0/Logon.svc?wsdl"
end
username = 'XXX'
password = 'YYY'
wsdl_logon.http.headers["Content-Type"] = "text/xml; charset=utf-8"
response = wsdl_logon.request "Logon" do
soap.body = {'Username' => username, 'Password' => password, 'WebServiceType' => 'Product'}
end
if response.http_error?
puts "Http Error!"
puts y response.http_error
else
puts "No Http Error!"
end
But I keep receiving 400 error messages ("bad request"). Or, if I remove the following line
wsdl_logon.http.headers["Content-Type"] = "text/xml; charset=utf-8"
I am receiving 415 error messages ("unsupported media type").
I have been using PHP to make these requests until now, and the following code always worked without problems:
$soap_logon = new SoapClient('https://api.affili.net/V2.0/Logon.svc?wsdl');
$token = $soap_logon->Logon(array(
'Username' => 'XXX',
'Password' => 'YYY',
'WebServiceType' => 'Product'
));
Can anybody point me to the right direction what a possible error source might be? I am completely lost right now.
Thank you for your help.
I did as Tom De Leu suggested, and tried to remove as many differences in the generated SOAP requests in question as possible. But I still keep receiving 400 errors. Any hint on possible reasons for this would be highly appreciated.
This is the (working) Request generated by PHP (linebreaks in XML added for clarity):
POST /V2.0/Logon.svc HTTP/1.1
Host: api.affili.net
Connection: Keep-Alive
User-Agent: PHP-SOAP/5.2.0-8+etch16
Content-Type: text/xml; charset=utf-8
SOAPAction: "http://affilinet.framework.webservices/Svc/ServiceContract1/Logon"
Content-Length: 456
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ns1="http://affilinet.framework.webservices/types"
xmlns:ns2="http://affilinet.framework.webservices/Svc"
>
<SOAP-ENV:Body>
<ns2:LogonRequestMsg>
<ns1:Username>xxx</ns1:Username>
<ns1:Password>yyy</ns1:Password>
<ns1:WebServiceType>Product</ns1:WebServiceType>
</ns2:LogonRequestMsg>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
This is the (not working) request generated by Ruby (again, xml linebreaks added for clarity)
SOAP request: https://api.affili.net/V2.0/Logon.svc
Content-Type: text/xml; charset=utf-8, SOAPAction: http://affilinet.framework.webservices/Svc/ServiceContract1/Logon, Content-Length: 605
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:wsdl="http://affilinet.framework.webservices/Svc"
SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ns1="http://affilinet.framework.webservices/types"
xmlns:ns2="http://affilinet.framework.webservices/Svc"
>
<SOAP-ENV:Body>
<ns2:LogonRequestMsg>
<ns1:Username>XXX</ns1:Username>
<ns1:Password>YYY</ns1:Password>
<wsdl:WebServiceType>Product</wsdl:WebServiceType>
</ns2:LogonRequestMsg>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
HTTPI executes HTTP POST using the httpclient adapter
SOAP response (status 400):
I found that I needed to add the headers in to get past the 415 error.
Savon.client(wsdl: "www.sample_doman.com/endpoint?wsdl", headers: {'Content-Type' => 'application/soap+xml; charset=utf-8'})
I would suggest looking at the XML sent by the PHP code, then comparing it with the XML sent by the Ruby Savon code, and check where the differences are. Then see whether you can modify your ruby code to generate the correct request.
Telling Savon to use SOAP version 2 (really 1.2) and then manually setting the content type to text/xml kind of defeats the purpose.
If your web service requires SOAP 1.2, then it is expecting a content type of 'application/soap+xml', which SAVON will do for you if you set the soap_version to 2.
If you want a content type of text/xml, just set your soap_version config variable to 1

Problem with Spring 3 + JSON : HTTP status 406?

I'm trying to get a list of Cities by sending the State name through Ajax in my SpringMVC 3.0 project.
For the purpose, I've used the following call (using jQuery) in my JSP:
<script type="text/javascript">
function getCities() {
jq(function() {
jq.post("getCities.html",
{ stateSelect: jq("#stateSelect").val()},
function(data){
jq("#cities").replaceWith('<span id="cities">Testing</span>');
});
});
}
</script>
And here's my Controller code:
#RequestMapping(value = "/getCities", method = RequestMethod.POST)
public #ResponseBody List<StateNames> getCities(#RequestParam(value="stateSelect", required=true) String stateName,
Model model) {
// Delegate to service to do the actual adding
List<StateNames> listStates = myService.listCityNames(stateName);
// #ResponseBody will automatically convert the returned value into JSON format
// You must have Jackson in your classpath
return listStates;
}
But I get HTTP 406 error stating the following when i run it:
406 Not Acceptable
The requested resource is only capable of generating content not acceptable according to the Accept headers sent in the request.
I've used Jackson in my Maven dependencies & have defined in my context file.
I've googled extensively & I guess the problem is #ResponseBody is not automatically converting my List to appropriate JSON object.
My Firebug says:
Response Headers
Server Apache-Coyote/1.1
Content-Type text/html;charset=utf-8
Content-Length 1070
Date Sat, 12 Feb 2011 13:09:44 GMT
Request Headers
Host localhost:8080
User-Agent Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2.13) Gecko/20101203 Firefox/3.6.13
Accept */*
Accept-Language en-us,en;q=0.5
Accept-Encoding gzip,deflate
Accept-Charset ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive 115
Connection keep-alive
Content-Type application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With XMLHttpRequest
Referer http://localhost:8080/MyApplication/
Content-Length 17
Cookie JSESSIONID=640868A479C40792F8AB3DE118AF12E0
Pragma no-cache
Cache-Control no-cache
Please guide me. What am i doing wrong?? HELP!!
As Peter had written in his comment, the cause of the problem is inability of Spring to load Jackson. It is not loaded by dependencies by default. After I've added the dependency
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-jaxrs</artifactId>
<version>1.9.2</version>
</dependency>
the JSON was returned after typing the address in the browser, without any tricks with Accept headers (as it is supposed to do).
Tested on Tomcat 7.0.
You have incorrect response content type it supposed to be application/json.
You need to add jackson to your /lib directory.
and you should have
<mvc:annotation-driven />
In your serlvet-name.xml file.
In addition I recommend you to map your request as get and try to browse it with Google Chrome,to see if it returns correct result. It has very good json representation.
The problem is not on server side, but on the client one.
Take a look at the error message carefully: The requested resource (generated by server side) is only capable of generating content (JSON) not acceptable (by the client!) according to the Accept headers sent in the request.
Examine your request headers:
Accept */*
Try this way:
function getCities() {
jq(function() {
jq.post(
"getCities.html", // URL to post to
{ stateSelect: jq("#stateSelect").val() }, // Your data
function(data) { // Success callback
jq("#cities").replaceWith('<span id="cities">Testing</span>');
},
"json" // Data type you are expecting from server
);
});
}
This will change your Accept header to the following (as of jQuery 1.5):
Accept: application/json, text/javascript, */*; q=0.01
This will explicitly tell the server side that you are expecting JSON.
Using jQuery , you can set contentType to desired one (application/json; charset=UTF-8' here) and set same header at server side.
REMEMBER TO CLEAR CACHE WHILE TESTING.
I too had a similar problem while using the Apache HTTPClient to call few services. The problem is the client and not the server. I used a HTTPRequester with header accepting application/json and it worked fine.

Resources