I have a web service with the following contract:
POST /Service/service.asmx HTTP/1.1
Host: xxx.xxx.xxx
Content-Type: text/xml; charset=utf-8
Content-Length: length
SOAPAction: "xxx.xxx.xxx/Service/Method"
<?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:Header>
<Request xmlns="xxx.xxx.xxx/Service/">
<transactiontype>string</transactiontype>
<username>string</username>
<password>string</password>
</Request>
</soap:Header>
<soap:Body>
<Method xmlns="xxx.xxx.xxx/Service/">
<xml>xml</xml>
</Method>
</soap:Body>
</soap:Envelope>
And I am trying to call the service using jquery. This is my code:
$.ajax({
url: serverUrl + 'Method',
type: "POST",
dataType: "xml",
data: { xml: "xml" },
beforeSend: function (req) {
req.setRequestHeader('Header', '<Request xmlns="xxx.xxx.xxx/Service/">'
+'<transactiontype>4</transactiontype>'
+'<agencyName>name</agencyName>'
+'<username>user</username>'
+'<password>pass</password>'
+'</Request>');
},
success: function (data) {
alert(data.text);
},
error: function (request, status, errorThrown) {
alert(status);
}
});
However, the header content is not passed to the web service? How would I go about passing the header credentials to my web service call?
soap:Header is an XML element inside the XML/SOAP data "payload". This is different than an HTTP headers. In the contract, SOAPAction (along with Content-Length, etc) is an HTTP header.
XmlHttpRequest.setRequestHeader is used for specifying HTTP headers. It has nothing to do with anything inside the XML (directly).
The first answer at Simplest SOAP example should give an example of how to make a SOAP request. Note:
xmlhttp.setRequestHeader("SOAPAction", "http://www.webserviceX.NET/GetQuote");
xmlhttp.setRequestHeader("Content-Type", "text/xml");
...
var xml = '<?xml version="1.0" encoding="utf-8"?>' +
'<soap:Envelope...' + etc;
xmlhttp.send(xml)
It is the XML which contains soap:Envelope and the child elements soap:Header and soap:Body.
Happy coding.
Related
I want to deploy an Apex class via REST API in a "single package" way. The deployment process begins and then fails with "No package.xml found" error. The manifest file is put directly in the root of the archive, however the API tells me that there is no manifest.
My request body looks in the following way
----------------------------BOUNDARY
Content-Disposition: form-data; name="entity_content"
Content-Type: application/json
{
"deployOptions": {
"allowMissingFiles": false,
"autoUpdatePackage": false,
"checkOnly": false,
"ignoreWarnings": false,
"performRetrieve": false,
"purgeOnDelete": false,
"rollbackOnError": true,
"runTests": [],
"singlePackage": true,
"testLevel": "NoTestRun"
}
}
----------------------------BOUNDARY
Content-Disposition: form-data; name="file"; filename="deploy.zip"
Content-Type: application/zip
UEsDBAoAAAAAAM4EL1Zi1oXYuQAAALkAAAALAAAAcGFja2FnZS54bWw8P3htbCB2ZXJzaW9uPSIxLjAiIGVuY29kaW5nPSJVVEYtOCI/PjxQYWNrYWdlIHhtbG5zPSJodHRwOi8vc29hcC5zZm9yY2UuY29tLzIwMDYvMDQvbWV0YWRhdGEiPjx0eXBlcz48bWVtYmVycz5BPC9tZW1iZXJzPjxuYW1lPkFwZXhDbGFzczwvbmFtZT48L3R5cGVzPjx2ZXJzaW9uPjU2LjA8L3ZlcnNpb24+PC9QYWNrYWdlPlBLAwQKAAAAAADOBC9WAAAAAAAAAAAAAAAACAAAAGNsYXNzZXMvUEsDBAoAAAAAAM4EL1aRdfeXigAAAIoAAAAWAAAAY2xhc3Nlcy9BLmNscy1tZXRhLnhtbDw/eG1sIHZlcnNpb249IjEuMCIgZW5jb2Rpbmc9IlVURi04Ij8+PEFwZXhDbGFzcyB4bWxucz0iaHR0cDovL3NvYXAuc2ZvcmNlLmNvbS8yMDA2LzA0L21ldGFkYXRhIj48YXBpVmVyc2lvbj41Ni4wPC9hcGlWZXJzaW9uPjwvQXBleENsYXNzPlBLAwQKAAAAAADOBC9WnojzmRIAAAASAAAADQAAAGNsYXNzZXMvQS5jbHNwdWJsaWMgY2xhc3MgQSB7IH1QSwECFAAKAAAAAADOBC9WYtaF2LkAAAC5AAAACwAAAAAAAAAAAAAAAAAAAAAAcGFja2FnZS54bWxQSwECFAAKAAAAAADOBC9WAAAAAAAAAAAAAAAACAAAAAAAAAAAABAAAADiAAAAY2xhc3Nlcy9QSwECFAAKAAAAAADOBC9WkXX3l4oAAACKAAAAFgAAAAAAAAAAAAAAAAAIAQAAY2xhc3Nlcy9BLmNscy1tZXRhLnhtbFBLAQIUAAoAAAAAAM4EL1aeiPOZEgAAABIAAAANAAAAAAAAAAAAAAAAAMYBAABjbGFzc2VzL0EuY2xzUEsFBgAAAAAEAAQA7gAAAAMCAAAAAA==
----------------------------BOUNDARY--
where Base64-encoded Zip file has the following structure
package.xml
classes/
A.cls
A.cls-meta.xml
and those three files look in the following way.
(package.xml)
<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
<types>
<members>A</members>
<name>ApexClass</name>
</types>
<version>56.0</version>
</Package>
(A.cls)
public class A { }
(a.cls-meta.xml)
<?xml version="1.0" encoding="UTF-8"?>
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>56.0</apiVersion>
</ApexClass>
I've also tried to set singlePackage to false and use unpackaged folder as a wrapper but I doesn't work, too.
There is a possibility that "No package.xml found" is a catch-all error that makes solving the problem harder than it should be.
I am trying to send a POST request using RobotFramework where the body of the request is XML.
Here is a Sample Robot file:
*** Settings ***
Library REST
*** Variables ***
${SERVER_URL} https://www.w3schools.com/xml/tempconvert.asmx
*** Test Cases ***
CL 1
[Tags] TC-CL
# Send SOAP via POST <?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>" <FahrenheitToCelsius xmlns="https://www.w3schools.com/xml/">" <Fahrenheit>100</Fahrenheit>" </FahrenheitToCelsius>" </soap:Body>"</soap:Envelope>
# Send SOAP via POST <?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> <FahrenheitToCelsius xmlns=\"https://www.w3schools.com/xml/\">\" <Fahrenheit>100</Fahrenheit> </FahrenheitToCelsius> </soap:Body></soap:Envelope>
# Send SOAP via POST <?xml version=\"1.0\" encoding=\"utf-8\"?>\n<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/\">\n <soap:Body>\n <FahrenheitToCelsius xmlns=\"https://www.w3schools.com/xml/\">\n <Fahrenheit>100</Fahrenheit>\n </FahrenheitToCelsius>\n </soap:Body>\n</soap:Envelope>
Send SOAP via POST <?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><FahrenheitToCelsius xmlns="https://www.w3schools.com/xml/"><Fahrenheit>100</Fahrenheit></FahrenheitToCelsius></soap:Body></soap:Envelope>
*** Keywords ***
Send SOAP via POST
[Arguments] ${body}
SET HEADERS {"SOAPAction": "https://www.w3schools.com/xml/FahrenheitToCelsius","Content-Type": "text/xml","Cache-Control": "no-cache"}
${resp}= POST ${SERVER_URL} data=${body}
Log ${resp} repr=true
When you run this code I get the error:
This is not a JSON string:
"data=<?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><FahrenheitToCelsius xmlns="https://www.w3schools.com/xml/"><Fahrenheit>100</Fahrenheit></FahrenheitToCelsius></soap:Body></soap:Envelope>"
FYI: The commented out versions of "Send SOAP via POST" are different ways I tried to get around the issue.
Here is sample python code using requests to ensure my endpoint works (once I get around that pesky "This is not a JSON string issue":
import requests
url = "https://www.w3schools.com/xml/tempconvert.asmx"
payload = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<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/\">\r\n <soap:Body>\r\n <FahrenheitToCelsius xmlns=\"https://www.w3schools.com/xml/\">\r\n <Fahrenheit>100</Fahrenheit>\r\n </FahrenheitToCelsius>\r\n </soap:Body>\r\n</soap:Envelope>"
payload = "<?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> <FahrenheitToCelsius xmlns=\"https://www.w3schools.com/xml/\">\" <Fahrenheit>100</Fahrenheit> </FahrenheitToCelsius> </soap:Body></soap:Envelope>"
payload = '<?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><FahrenheitToCelsius xmlns="https://www.w3schools.com/xml/"><Fahrenheit>100</Fahrenheit></FahrenheitToCelsius></soap:Body></soap:Envelope>'
headers = {
'SOAPAction': "\"https://www.w3schools.com/xml/FahrenheitToCelsius\"",
'Content-Type': "text/xml",
'Cache-Control': "no-cache",
}
response = requests.request("POST", url, data=payload, headers=headers)
print(response.text)
The problem seems to be in the RESTInstance code here
The initial issue which is what throws the error (see Commented line below):
#keyword
def post(self, endpoint, body=None, timeout=None, allow_redirects=None,
validate=True, headers=None):
"""Make a ``POST`` request call to a specified ``endpoint``.
Example:
POST "Mr Potato" to endpoint and ensure status code is 201
| `POST` | /users | { "id": 11, "name": "Mr Potato" } |
| `Integer` | response status | 201 |
"""
endpoint = self._input_string(endpoint)
request = deepcopy(self.request)
request['method'] = "POST"
request['body'] = self.input(body) # <== ERROR THROWS HERE
if allow_redirects is not None:
request['allowRedirects'] = self._input_boolean(allow_redirects)
if timeout is not None:
request['timeout'] = self._input_timeout(timeout)
validate = self._input_boolean(validate)
if headers:
request['headers'].update(self._input_object(headers))
return self._request(endpoint, request, validate)['response']
The root issue is that the _request code forces body to be used in the json parameter of the requests.requests call (aka client based on import) see code snippet from same file below:
def _request(self, endpoint, request, validate=True):
if endpoint.endswith('/'):
endpoint = endpoint[:-1]
if not endpoint.startswith(('http://', 'https://')):
base_url = self.request['scheme'] + "://" + self.request['netloc']
if not endpoint.startswith('/'):
endpoint = "/" + endpoint
endpoint = urljoin(base_url, self.request['path']) + endpoint
request['url'] = endpoint
url_parts = urlparse(request['url'])
request['scheme'] = url_parts.scheme
request['netloc'] = url_parts.netloc
request['path'] = url_parts.path
try:
response = client(request['method'], request['url'],
params=request['query'],
json=request['body'], #<== ROOT CAUSE HERE
headers=request['headers'],
proxies=request['proxies'],
cert=request['cert'],
timeout=tuple(request['timeout']),
allow_redirects=request['allowRedirects'],
verify=request['sslVerify'])
When sending XML using the requests library you need to use body= not json=
Have the following code in my Default.aspx file, located at http://localhost/idss/Default.aspx:
<%# Page Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<head id="Head1" runat="server">
<title>Testing IDSS Return Values</title>
</head>
<body>
<%#
// how we do it
XmlDocument doc = new XmlDocument();
doc.Load(Server.MapPath("idss/requests/categoryList.xml"));
// create the request to your URL
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://localhost/idss/Default.aspx");
// add the headers
// the SOAPACtion determines what action the web service should use
// YOU MUST KNOW THIS and SET IT HERE
request.Headers.Add("SOAPAction", "http://ws.idssasp.com/Members.asmx/GetCategoryList");
// set the request type
// we use utf-8 but set the content type here
request.ContentType = "text/xml;charset=\"utf-8\"";
request.Accept = "text/xml";
request.Method = "POST";
// add our body to the request
Stream stream = request.GetRequestStream();
doc.Save( stream );
stream.Close();
// get the response back
using(HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
request.Write(response);
}//end using
%>
</body>
</html>
The xml file located at: http://localhost/idss/requests/categoryList.xml looks like this:
<?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:Header>
<AuthorizeHeader xmlns="http://ws.idssasp.com/Members.asmx">
<UserName>MyUsername</UserName>
<Password>MyPassword</Password>
</AuthorizeHeader>
</soap:Header>
<soap:Body>
<GetCategoryList xmlns="http://ws.idssasp.com/Members.asmx" />
</soap:Body>
</soap:Envelope>
Where MyUsername and MyPassword is filled in with the correct username and password. The URL located here: http://ws.idssasp.com/members.asmx?op=GetCategoryList&pn=0 tells me that SOAP should send a request like this:
POST /members.asmx HTTP/1.1
Host: ws.idssasp.com
Content-Type: text/xml; charset=utf-8
Content-Length: length
SOAPAction: "http://ws.idssasp.com/Members.asmx/GetCategoryList"
<?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:Header>
<AuthorizeHeader xmlns="http://ws.idssasp.com/Members.asmx">
<UserName>string</UserName>
<Password>string</Password>
</AuthorizeHeader>
</soap:Header>
<soap:Body>
<GetCategoryList xmlns="http://ws.idssasp.com/Members.asmx" />
</soap:Body>
</soap:Envelope>
But when I browse to http://localhost/idss/Default.aspx I get an Internal Server Error (500). What exactly am I doing wrong here? Do I need to add namespaces? Or other References somewhere in the Default.aspx file? If so, which one's are needed? Also, am I pointing to the correct in (HttpWebRequest)WebRequest.Create("http://localhost/idss/Default.aspx");?
Am I doing this correctly? I just feel like something is missing here.
I've got a ASP.NET WebService that looks something like this:
[WebMethod]
public static void DoSomethingWithStrings(string stringA, string stringB)
{
// and so on
}
An third party application should call this webservice. However this application encodes strings as UTF-8 and all umlauts are replaced by '??'. I can view the call and the special characters are formatted well:
<?xml version="1.0" encoding="utf-8" ?>
<!-- ... -->
<SoapCall>
<DoSomethingWithStrings>
<stringA>Ä - Ö - Ü</stringA>
<stringB>This is a test</stringB>
</DoSomethingWithStrings>
</SoapCall>
This produces the following output, when I simply print the strings inside the webservice method:
?? - ?? - ??
This is a test
How can I configure the WebService to accept UTF-8 encoded strings?
Update
Fiddler also tells me that the content-type charset of the http request is UTF-8.
Update 2
I tried to add following code to global.asax for debugging purposes:
public void Application_BeginRequest(object sender, EventArgs e)
{
using (var reader = new System.IO.StreamReader(Request.InputStream))
{
string str = reader.ReadToEnd();
}
}
This reads the actual SOAP call. The StreamReaders encoding is set to UTF-8. The SOAP call looks correct:
<?xml version="1.0" encoding="UTF-8" ?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Body>
<DoSomethingWithStrings xmlns="http://www.tempuri.org/">
<stringA>Ä - Ö - Ü</stringA>
<stringB>This is a test!</stringB>
</DoSomethingWithStrings>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
In the web.config file the globalization settings are set correctly:
<globalization requestEncoding="UTF-8" responseEncoding="UTF-8" culture="de-DE" uiCulture="de-DE" />
So it looks like something that deserializes the SOAP message does not use UTF-8 but ASCII encoding.
Finally it turns out that something went wrong within accepting HTTP-Messages. I don't actually know what manipulates the HTTP-Request, but I found a workaround for this. Eventhough Fiddler showed me the correct content type (text/xml; charset=utf-8) in my Application_BeginRequest the Request.RequestContext.HttpContext.Request.ContentType was just text/xml, which lead to a fallback to default (ASCII) encoding within the ASMX serializer. I've added the following code to the Application_BeginRequest handler and everything works for now.
if (Request.RequestContext.HttpContext.Request.ContentType.Equals("text/xml"))
{
Request.RequestContext.HttpContext.Request.ContentType = "text/xml; charset=UTF-8";
}
Thanks for your help!
Try this:-
byte[] bytes=Encoding.UTF8.GetBytes(yourString);
NOTE:-
Strings never contain anything utf-* or anything else encoded
The SOAP call is being decoded as ASCII somewhere - each of the umlauts are 2 bytes with high bit being set, which turns into ?? when decoded as ASCII.
So, something like this is happening:
byte[] bytesSentFromClient = Encoding.UTF8.GetBytes("Ä - Ö - Ü");
string theStringIThenReceiveInMyMethod = Encoding.ASCII.GetString(bytesSentFromClient);
Console.WriteLine(theStringIThenReceiveInMyMethod);
//?? - ?? - ??
To verify this is happening for sure, you should compare stringA == "Ä - Ö - Ü" rather than printing it somewhere.
I guess you could start by doing a project-wide search for "ASCII" and then work from there if you find anything.
You could also try
<globalization requestEncoding="utf-8" responseEncoding="utf-8"/>
Under the <system.web> tag in Web.config file.
I had the same problem. Asmx web service converted my UTF-8 to ASCII or, better to say to ??????. Your post helped me a lot.
The solution I found was to change version of SOAP protocol from 1.1 to 1.2
I mean:
POST /WebService1.asmx HTTP/1.1
Host: www.tempuri.org
Content-Type: text/xml; charset=utf-8
Content-Length: length
SOAPAction: "http://www.tempuri.org/HelloWorld"
<?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>
<HelloWorld xmlns="http://www.tempuri.org/">
<inputParam>Привет</inputParam>
</HelloWorld>
</soap:Body>
</soap:Envelope>
had the problem. But when I changed my request to SOAP 1.2:
POST /WebService1.asmx HTTP/1.1
Host: www.tempuri.org
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>
<HelloWorld xmlns="http://www.tempuri.org/">
<inputParam>Привет</inputParam>
</HelloWorld>
</soap12:Body>
</soap12:Envelope>
The issue was solved.
SOAP Request<?xml version="1.0" encoding="UTF-8"?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Header/>
<S:Body>
<ns2:deleteDataView xmlns:ns2="http://ws.$$$$$.#####.####.com/">
<identifier>5</identifier>
</ns2:deleteDataView>
</S:Body>
</S:Envelope>
SOAP Response<?xml version="1.0" encoding="UTF-8"?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body>
<ns2:deleteDataViewResponse xmlns:ns2="http://ws.$$$$$.#####.####.com/">
<return>ERROR: A bug has been encountered,please try later</return>
</ns2:deleteDataViewResponse>
</S:Body>
</S:Envelope>
I want to read SOAP response in flex,am some what new to FLEX,pls help,even good resources will work.
Handling SOAP Response
<mx:WebService
id="userRequest"
wsdl="http://www.gnpcb.org/esv/share/soap/index.php?wsdl">
<mx:operation name="doPassageQuery" resultFormat="object"
fault="mx.controls.Alert.show(event.fault.faultString)"
result="showResult(event)"/>
</mx:WebService>
In the above code you are accessing your SOAP WebService, now you have the resultFormat is an Object and the result function is showResult()
private function showResult(e:ResultEvent):void
{
trace(e.result);
}
Resources
http://www.flexlive.net/?p=79