SOAP Messages on iPhone - iphone

I have to use several SOAP messages to get data from a web service. I got some examples how to do that but they all have the XML (http://icodeblog.com/2008/11/03/iphone-programming-tutorial-intro-to-soap-web-services/)
// ---- LOGIN -----
NSString *soapMessage = [NSString stringWithFormat:
#"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
"<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\">\n"
"<soap12:Body>\n"
"<Login xmlns=\"http://tempuri.org/\">\n"
"<sUserID>USER</sUserID>\n"
"<sUserPw>PASSWORD</sUserPw>\n"
"<sDomain>SERVER</sDomain>\n"
"</Login>\n"
"</soap12:Body>\n"
"</soap12:Envelope>\n"
];
NSString *urlToSend = [[NSString alloc] initWithString:#"http://SERVER/DIRECTORY/WSDL_FILE.ASMX"];
NSString *callTOMake = [[NSString alloc] initWithString:#"http://WEBSERVER/Login"];
TWO questions:
1) Does it make sense to read the SOAP Message from a class or a file into xcode?? or sould I just define them thru the code ??
2) I used SOAPUI & .NET to query the service. It works fine... but when I do it from the iphone simulator it returns the following:
2010-03-10 15:13:54.773 Hello_SOAP[91204:207] soap:ClientServer did not recognize the value of HTTP Header SOAPAction: http://WEBSERVER/DIRECTORY/Login
How can I figure out what the issue is that's causing the said error on the simulator??

OK... I have one solution for my issues...(#2) instead of writing the code and figuring if things will work by trial and error, I used Todd Ditchendorf SOAP Client http://code.google.com/p/mac-soapclient/
That way you can figure out what the SOAP call is a lot easier and just drop it on the code... BTW: you will get the pretty format of the request and response... that way you can format you lines of the code accordingly...
Hope this helps

Related

iPhone - Strange behaviour when '&' is included in HTTP request body

I've got a very strange problem related to sending POST request from my iPhone app.
The app needs to send the HTTP post data to a third-party service. Request is XML and it'll get XML response. Here's my code for sending the request:
-(void)sendRequest:(NSString *)aRequest
{
//aRequest parameter contains the XML string to send.
//this string is already entity-encoded
isDataRequest = NO;
//the following line will created string REQUEST=<myxml>
NSString *httpBody = [NSString stringWithFormat:#"%#=%#",requestString,aRequest];
//I'm not sure what this next string is doing, frankly, as I didn't write this code initially
httpBody = [(NSString*)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)httpBody, NULL, CFSTR("+"), kCFStringEncodingUTF8) autorelease];
NSData *aData = [httpBody dataUsingEncoding:NSUTF8StringEncoding];
NSMutableURLRequest *request = [[[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:kOOURLRequest]] autorelease];
[request setHTTPBody:aData];
[request setHTTPMethod:#"POST"];
self.feedURLConnection = [[[NSURLConnection alloc] initWithRequest:request delegate:self] autorelease];
}
This works perfectly well as long as the request XML doesn't contain & symbol, for example, this XML request:
<?xml version="1.0"?>
<request type="search" group="0" language="en" version="2.5.2">
<auth>
<serial>623E1579-AC18-571B-9022-3659764542E7</serial>
</auth>
<data>
<location>
<lattitude>51.528536</lattitude>
<longtitude>-0.108865</longtitude>
</location>
<search>archive</search>
</data>
</request>
is sent as expected and the correct response is received as expected.
However, when the request contains & character (specifically in the "search" element) - like so:
<?xml version="1.0"?>
<request type="search" group="0" language="en" version="2.5.2">
<auth>
<serial>623E1579-AC18-571B-9022-3659764542E7</serial>
</auth>
<data>
<location>
<lattitude>51.528536</lattitude>
<longtitude>-0.108865</longtitude>
</location>
<search>& archive</search>
</data>
</request>
Only everything up to the & character is sent to the server. The server doesn't seem to receive anything beyond this character. Note that I have a pretty much the same code working in an Android app and everything is working correctly, so it's not a problem on the server.
Any ideas how I can get this fixed would be greatly appreciated!
Thanks to Zaph's comment, I finally sorted it. I used WireShark to see what was actually sent to the server and discovered that the request wasn't encoded completely. In the final HTTP body the actual symbol & was present (part of &). This naturally didn't work very well on the server side, because it was receiving something like:
REQUEST=first_half_of_request&second_half_of_request
When the server decoded the POST variables, & was taken as the separator of variables, therefore the REQUEST variable was only set to the first_half_of_request - everything up to the & char.
The solution was quite simple. In line
httpBody = [(NSString*)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)httpBody, NULL, CFSTR("+"), kCFStringEncodingUTF8) autorelease];
replace CFSTR("+") with CFSTR("+&") to encode & as well. Now this, combined with entity encoding (& for &), resulted in the correct data being sent to the server and the correct response being received.

Encoding on NSURLConnection

I need to load data from a REST service, but the result is always (null) when I have any accentuation. I know this is an encoding problem but NSUrlConnection gives me no solution. The best result I got is to have all my text with strange codes in the place of the accentuated characters.
I already tried to use NSUrl like the following code and it works, but I need to set two headers for this connection.
NSURL *nsurl = [[NSURL alloc] initWithString:url];
NSString *data = [[NSString alloc] initWithContentsOfURL:nsurl encoding: NSUTF8StringEncoding error: nil];
Well I could have two solutions for this taks, adding headers do NSUrl connection or manage to make the encoding to work in NSURLConnection.
Does anyone have a solution?
You can add header fields for your request in an NSMutableURLRequest instance with setValue:forHTTPHeaderField:

objective c http query

Hey, Iam new to objective c and really dont know much about it. I have been given a query that is gonna I need to send data in to the server.Query is like this http://abc.com/insertipademail.php?name=name&email=email I need to enter the name and email I have constructed the string But I dont know how to send it to the server. Can someone help me out please. Or point me in the right direction. Thanks
For starters, take a look a NSString's stringWithContentsOfURL:encoding:error: method. You could do something like:
// NSString * myURLString = whatever you do to build the url
NSURL * myURL = [NSURL URLWithString: myURLString];
NSString * response = [NSString stringWithContentsOfURL: myURL encoding: NSUTF8StringEncoding error: NULL];
NSLog(#"The response was: %#", response);
As written, this will ignore all errors and perform the request synchronously. In a real app, you probably want to handle any error that occur, and perhaps perform the request in the background. See the URL Loading System Programming Guide for further documentation. You can also try using any of several open source libraries such as those suggested in David M.'s answer.
I like the library ASIHTTPRequest. There is also HTTPRiot.

NSXMLParser init with XML in NSString format

I just ran into this one and couldn't seem to get any clear answer from the documentation.
Im retrieving some XML through a HTTPS connection. I do all sorts of authentication etc. so I have a set of classes that deals with this in a nice threaded way.
The result is an NSString that goes something like:
<response>
//some XML formatted test
</response>
This means that there is no encoding="UTF-8" indent="yes" method="xml" or other header blocks to indicate that this is actual XML and not just an NSString.
I guess I will use [NSXMLParser initWithData:NSData] to construct the parser, but how will I format or cast my NSString of xml formatted text into a proper NSData object that NSXMLParser will understand and parse?
Hope it makes sense, thank you for any help given :)
You can convert a string to a NSData object using the dataUsingEncoding method:
NSData *data = [myString dataUsingEncoding:NSUTF8StringEncoding];
You can then feed this to NSXMLParser.
The headers are optional, but you can insert the appropriate headers yourself if needed:
NSString *header = #"<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
NSString *xml = [NSString stringWithFormat:#"%#\n%#", header, response);
NSData *data = [xml dataUsingEncoding:NSUTF8StringEncoding];
NSXMLParser *praser = [NSXMLParser initWithData:data];
By the time NSXMLParser has the data it's pretty much going to be expecting it to be XML ;-)
I'm pretty sure the processing instruction header is optional in this context. The way you get the NSString into the NSData is going to dictate the encoding (using dataUsingEncoding:).
(edit: I was looking for the encoding enum, but Philippe Leybaert beat me to it, but to repeat it here anyway, something like: [nsString dataUsingEncoding:NSUTF8StringEncoding])
I've passed NSStrings of XML in this way before with no issues.
Not specific to this question as such, but on the subject of XML parsing in an iPhone context in general you may find this blog entry of mine interesting, too.

iPhone URL Request: Add value to HTTP header field

I'm trying to add a value to the header for a URL request.
Something like this works just fine:
[urlRequest addValue:#"gzip" forHTTPHeaderField:#"Accept-Encoding"];
But this doesn't even show up in the header:
NSString *authString = [[NSString alloc] initWithString:
[defaults objectForKey:#"auth"]];
[urlRequest addValue:authString forHTTPHeaderField:#"iphoneID"];
I'm completely stumped. The auth string is around 90 characters long. Is this a problem?
Edit:
Here's the code I'm trying:
NSString *authString = [[NSString alloc] initWithString:[defaults objectForKey:#"auth"]];
[urlRequest addValue:authString forHTTPHeaderField:#"iphoneid"];
[urlRequest addValue:#"gzip" forHTTPHeaderField:#"Accept-Encoding"];
I can see the Accept-Encoding header being sent through Wireshark, but iphoneid is nowhere to be found. It's just a string, 80-90 characters long.
Another Update:
So it seems that the problem isn't the field "iphoneid" but rather the authString I'm trying to pass into it. Other strings that I just create with the #"something" work fine, but the auth string that I pull from NSUserDefaults doesn't appear.
Suggestions on how to debug this?
The true problem.
The string I was pulling from NSUserDefaults already had a line ending. When set as a header, another \r\n is appended, which apparently isn't valid. Thus, the header wouldn't appear in any outgoing packets.
The fix:
Use this to trim off the characters before setting as a header value.
[yourString stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceAndNewlineCharacterSet]];
Testing checklist:
Verify that you actually have a NSMutableURLRequest (and not a NSURLRequest) at this point. In particular, check your logs for an exception due to "unrecognized selector."
Verify that urlRequest is not nil.
Switch to setValue:forHTTPHeaderField: rather than addValue:forHTTPHeaderField:.
Swap the forHTTPHeaderField: value to #"Accept-Encoding" to see if the field is the problem
Swap #"gzip" for auth to see if the value is the problem.
You need Charles web proxy, to see what header values are really outbound and inbound. Then you can see if the problem is really in your code or some magic on the server discarding things.
There's a free trial, and after you install it if you hit record any traffic the simulator sends will go through the proxy. Very nice.
http://www.charlesproxy.com/