Web service iPhone - iphone

I'm trying to connect to a web service, with the next code:
NSURL *soapURL;
WSMethodInvocationRef soapCall;
NSString *methodName;
NSMutableDictionary *params;
NSDictionary *result;
soapURL = [NSURL URLWithString:#"http://wicaweb2.intec.ugent.be:80/FaceTubeWebServiceService/FaceTubeWebService?WSDL"];
methodName = #"getMostViewed";
soapCall = WSMethodInvocationCreate((CFURLRef)soapURL,
(CFStri ngRef)methodName, kWSSOAP2001Protocol);
params = [NSMutableDictionary dictionaryWithCapacity:2];
[params setObject:#"1" forKey:#"arg0"];
[params setObject:#"all_time" forKey:#"arg1"];
NSArray *paramsOrder = [NSArray arrayWithObjects:#"arg0",#"arg1", nil];
WSMethodInvocationSetParameters(soapCall,
(CFDictionaryRef)params,(CFArrayRef)paramsOrder);
WSMethodInvocationSetProperty(soapCall,
kWSSOAPMethodNamespaceURI,
(CFTypeRef)#"http://webservice.facetube.wica.intec.ugent.be/");
result = (NSDictionary*)WSMethodInvocationInvoke(soapCall);
NSString *resultado = [result objectForKey: (NSString*)kWSMethodInvocationResult];
NSLog(#"Result:%#",resultado);
But I obtain the same reply, than if I don't send parameters.
I got this:
[Session started at 2009-07-07 22:01:53 +0200.]
2009-07-07 22:01:57.669 Hello_SOAP[6058:20b] Result:{
}
Exactly, seems like this but I will show you also the parameters that the method needs:
SOAP Request
> <?xml version="1.0" encoding="UTF-8"?>
> <soapenv:Envelope
> xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
> xmlns:xsd="http://www.w3.org/2001/XMLSchema"
> xmlns:ns1="http://webservice.facetube.wica.intec.ugent.be/">
> <soapenv:Body>
> <ns1:getMostViewed>
> <arg0>1</arg0>
> <arg1>all_time</arg1>
> </ns1:getMostViewed>
> </soapenv:Body> </soapenv:Envelope>
As you can see, the name of the parameters that I need are arg0 and arg1, for this I can't understand what is going wrong :)

Try posting the reply you get. It seems like you're parameters are incorrect, given that you get the same response as if you sent no parameters.

Danger. Are you are aware that WSMethodInvocationRef (or any of the SOAP helper classes) do not exist on the iPhone? (your question is tagged as iPhone).
It will compile for the simulator but not for the phone. I'd hate to see you waste much time getting this working if your real target is the device and not the Mac.
Instead use wsdl2objc.
Who knows, that may well solve your problem - since it's a stub generation approach it probably will work fine.
If possible though, I'd recommend using REST for server communication instead of SOAP. Depends on what control you have over the server.

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.

how to fetch XML code in simple array format in objective c?

I am just a beginner in i-phone development and right now i am developing one facebook application. thing is that i need to fetch data from webservice where data is in such format :
HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: length
<?xml version="1.0" encoding="utf-8"?>
<soap:Body>
<abc1>string</abc1>
<abc2>string</abc2>
<abc3>string</abc3>
</soap:Body>
</soap:Envelope>
where abc is a variable from which i need to fetch data.problem comes here,i am not aware how to fetch data from this using either json or xml.
Can anybody help me out please??
Thank you in advance.
You may try to use TouchXML
CXMLDocument *theXMLDocument = [[[CXMLDocument alloc] initWithXMLString:yourXMLString options:0 error:&theError] autorelease];
NSArray *theNodes = NULL;
theNodes = [theXMLDocument nodesForXPath:#"//root" error:&theError];
for (CXMLElement *theElement in theNodes)
{
theNodes = [theElement nodesForXPath:#"./abc" error:NULL];
NSLog(#"%#", theNodes);
}
Disclaimer: I am going to suggest product of my own company, but its a good suggestion for this question.
Why dont you try web service connectivity tools like,
KSoap
WSClient++ etc

SOAP Messages on 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

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.

Creating a highscore like system, iPhone side

I'm sorry for opening a new question, I had to - as I wrote the other question from my iPhone as unregistered user and it is not very comfortable to write from the iPhone.
Rephrasing the question:
Is it possible to use the:
[NSMutableArray writeToURL:(NSString *)path atomically:(BOOL)AuxSomething];
In order to send a file (NSMutableArray) XML file to a url, and update the url to contain that file?
for example:
I have an array and I want to upload it to a specific URL and the next time the app launches I want to download that array.
NSMutableArray *arrayToWrite = [[NSMutableArray alloc] initWithObjects:#"One",#"Two",nil];
[arrayToWrite writeToURL:
[NSURL urlWithString:#"mywebsite.atwebpages.com/myArray.plist"] atomically:YES];
And at runtime:
NSMutableArray *arrayToRead =
[[NSMutableArray alloc] initWithContentsOfURL:[NSURL urlWithString:#"mywebsite.atwebpages.com/myArray.plist"]];
Meaning, I want to write an NSMutableArray to a URL, which is on a web hosting service (e.g. batcave.net), the URL receives the information and updates server sided files accordingly.
A highscore like setup, user sends his scores, the server updates it's files, other users download the highscores at runtime.
I hope this is clarified.
Edit: What I am looking for is scripting PHP or ASP so the website, the URL where the data is sent to would know how to handle it. I want an example or a tutorial on how to implement this scripting for handling data, if it's possible to do this on a web hosting service.
~Thanks in advance.
To answer the question "How do I create a high score like system?", there are multiple parts of the system:
You need an ID for each user (a GUID generated on the iPhone, together with the users name should be sufficient).
You need a server that: remembers high scores; receives high scores from users; either displays (on a web site) the high scores and/or makes the high scores available for download to the phone.
You need some fraud protection, although that is likely fighting a losing battle against jailbreakers.
On the iPhone app side, you might want to be able to download the current high scores for display, which is done easily enough with something like:
int statusCode = 0;
NSData* result = nil;
NSHTTPURLResponse* response = nil;
NSError* error = nil;
NSString* url = #"http://www.yourserver.com/highscores.php"; // returns XML plist data
NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url] cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData timeoutInterval:180];
result = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
// NSLog( #"NSURLConnection result %d %# %#", [response statusCode], [request description], [error description] );
statusCode = [response statusCode];
if ( (statusCode == 0) || (!result && statusCode == 200) ) {
statusCode = 500;
}
Since it is synchronous, you might want to put it inside an NSOperation. Alternatively, you can use
+ (NSURLConnection *)connectionWithRequest:(NSURLRequest *)request delegate:(id)delegate
To send high score data, because it is so small, the easiest way is simply to encode it in the URL.
NSString* url = [NSString stringWithFormat:#"http://www.yourserver.com/sethighscores.php?uid=%#;name=%#;score=%d;antifraud=%#", [uid encodeParameter], [name encodeParameter], score, [secureHash encodeParameter]];
Where encodeParameter is a custom category on NSString that encodes URL parameters and secureHash is a string representing a one way secure hashing of the uid, name, score and some secret known to your iPhone app and your web site. You'll need to figure these out on your own or ask separate questions since this is already getting long.
According to NSData writeToURL docs (at least for iPhone OS 2.2.1):
"Since at present only file:// URLs are supported, there is no difference between this method and writeToFile:atomically:, except for the type of the first argument."
Although the docs for NSArray/NSDictionary/NSString do not specifically mention the restriction, it would seem highly likely that the same restriction applies.
So you will have to upload the XML using some other mechanism.
Also, web sites generally are read only, unless you provide specific code on the web server to support uploading.