Looks like no one’s replied in a while. To start the conversation again, simply ask a new question.

How to consume SOAP web service by passing parameters through Xcode 4.3

Im new to IOS programming. Can any one guide me "How to consume a simple parametarized dot net web service through Xcode. I have tried all the solutions which I found from the net but all are giving errors or returning NULL value from the web service."

Your help will be highly appreciated.

Thank u.

iPad 2, Mac OS X (10.7)

Posted on May 18, 2012 2:27 AM

Reply
16 replies

May 19, 2012 10:52 AM in response to munna1116

Xcode itself has no features to automatically generate web service client proxies. You must roll your own client. This give you great flexibility but is a pain.


Some developers stick with Apple's NSURLConnection classes and code all aspects of HTTP request management. Others use 3rd-party libraries so they don't have to write their own code for reachability, authentication, error handling, asynchronous operations, etc.


If you mean SOAP web services, here is an example that consumes a publicly available sample .NET web service to convert temperatures. I used NSURLConnection in this example. Handling REST web services is very similar, but there is no SOAP envelope, and the response data is not necessarily XML.


@interface ViewController : UIViewController {

NSMutableData *responseData;

}


@property (weak, nonatomic) IBOutlet UITextField *temperatureTextField;

@property (weak, nonatomic) IBOutletUILabel *resultLabel;


- (IBAction)convertButton_TouchUpInside:(id)sender;


@end

...

- (IBAction)convertButton_TouchUpInside:(id)sender {

// construct envelope (not optimized, intended to show basic steps)

NSString *envelopeText =

@"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"

"<soap12:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema- to instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap12=\"http://www.w3.org/2003/05/soap-envelope\">\n"

" <soap12:Body>\n"

" <CelsiusToFahrenheit xmlns=\"http://tempuri.org/\">\n"

" <Celsius>%@</Celsius>\n"

" </CelsiusToFahrenheit>\n"

" </soap12:Body>\n"

"</soap12:Envelope>";

envelopeText = [NSString stringWithFormat:envelopeText, temperatureTextField.text];

NSData *envelope = [envelopeText dataUsingEncoding:NSUTF8StringEncoding];


// construct request

NSString *url = @"http://www.w3schools.com/webservices/tempconvert.asmx";

NSMutableURLRequest *request = [NSMutableURLRequestrequestWithURL:[NSURLURLWithString:url] cachePolicy:NSURLRequestUseProtocolCachePolicytimeoutInterval:30.0];

[request setHTTPMethod:@"POST"];

[request setHTTPBody:envelope];

[request setValue:@"application/soap+xml; charset=utf-8"forHTTPHeaderField:@"Content-Type"];

[request setValue:[NSStringstringWithFormat:@"%d", [envelope length]] forHTTPHeaderField:@"Content-Length"];


// fire away

NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];

if (connection)

responseData = [NSMutableData data];

else

NSLog(@"NSURLConnection initWithRequest: Failed to return a connection.");

}


- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response

{

[responseDatasetLength:0];

}


- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data

{

[responseData appendData:data];

}


- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error

{

NSLog(@"connection didFailWithError: %@ %@",

error.localizedDescription,

[error.userInfoobjectForKey:NSURLErrorFailingURLStringErrorKey]);

}


- (void)connectionDidFinishLoading:(NSURLConnection *)connection

{

// extract result using regular expression (only as an example)

// this is not a good way to do it; should use XPath queries with XML DOM such as GDataXMLDocument

NSString *responseText = [[NSStringalloc] initWithData:responseDataencoding:NSUTF8StringEncoding];

NSString *pattern = @"<CelsiusToFahrenheitResult>(\\d+\\.?\\d*)</CelsiusToFahrenheitResult>";

NSError *error = NULL;

NSRegularExpression *regex = [NSRegularExpressionregularExpressionWithPattern:pattern options:NSRegularExpressionCaseInsensitiveerror:&error];

NSTextCheckingResult *match = [regex firstMatchInString:responseText options:0 range:NSMakeRange(0, responseText.length)];

if (match)

resultLabel.text = [responseText substringWithRange:[match rangeAtIndex:1]];

else

resultLabel.text = @"Response error.";

}

May 24, 2012 10:15 AM in response to munna1116

The code which you gave, helped me alot. But by doing some small changed i got the result.

Here is the Code for consuming a sample Webservice .......Its working great to me....


- (IBAction)convertButton:(id)sender {

// construct envelope (not optimized, intended to show basic steps)

NSString *envelopeText =[NSString stringWithFormat:@"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" "<soap12:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema- to instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap12=\"http://www.w3.org/2003/05/soap-envelope\">\n" " <soap12:Body>\n" " <CelsiusToFahrenheit xmlns=\"http://tempuri.org/\">\n" " <Celsius>%@</Celsius>\n" " </CelsiusToFahrenheit>\n" " </soap12:Body>\n" "</soap12:Envelope>",temperatureTextField.text];

envelopeText = [NSString stringWithFormat:envelopeText, temperatureTextField.text];

NSData *envelope = [envelopeText dataUsingEncoding:NSUTF8StringEncoding];

// construct request

NSString *url = @"http://www.w3schools.com/webservices/tempconvert.asmx";

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:30.0];


[request addValue:@"http://tempuri.org/CelsiusToFahrenheit" forHTTPHeaderField:@"SOAPAction"];


[request setHTTPMethod:@"POST"];

[request setHTTPBody:envelope];

[request setValue:@"application/soap+xml; charset=utf-8"

forHTTPHeaderField:@"Content-Type"];

[request setValue:[NSString stringWithFormat:@"%d", [envelope length]]forHTTPHeaderField:@"Content-Length"];

// fire away

NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];

if (connection)

responseData = [NSMutableData data];

else

NSLog(@"NSURLConnection initWithRequest: Failed to return a connection.");

}



- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response

{

[responseData setLength:0]; }

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {

[responseData appendData:data];

}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {

NSLog(@"connection didFailWithError: %@ %@", error.localizedDescription,

[error.userInfo objectForKey:NSURLErrorFailingURLStringErrorKey]);

}


- (void)connectionDidFinishLoading:(NSURLConnection *)connection {

NSLog(@"DONE. Received Bytes:%d",[responseData length]);

NSString *theXml = [[NSString alloc] initWithBytes:[responseData mutableBytes] length:[responseData length] encoding:NSUTF8StringEncoding];

NSLog(@"The final result :%@",theXml);


if(xmlParser)

{


}

xmlParser = [[NSXMLParser alloc] initWithData: responseData];

[xmlParser setDelegate:self];

[xmlParser setShouldResolveExternalEntities:YES];

[xmlParser parse];

}


//---when the start of an element is found---

-(void) parser:(NSXMLParser *) parser didStartElement:(NSString *) elementName namespaceURI:(NSString *) namespaceURI qualifiedName:(NSString *) qName attributes:(NSDictionary *)attributeDict {

if( [elementName isEqualToString:@"CelsiusToFahrenheitResult"])

{

if (!soapResults)

{

soapResults = [[NSMutableString alloc] init];

}

elementFound = YES;

}

}



-(void)parser:(NSXMLParser *) parser foundCharacters:(NSString *)string

{

if (elementFound)

{

[soapResults appendString: string];

}

}


//---when the end of element is found---

-(void)parser:(NSXMLParser *)parser

didEndElement:(NSString *)elementName

namespaceURI:(NSString *)namespaceURI

qualifiedName:(NSString *)qName

{

if ([elementName isEqualToString:@"CelsiusToFahrenheitResult"])

{

//---displays the country---

NSLog(@"%@",soapResults);

UIAlertView *alert = [[UIAlertView alloc]

initWithTitle:@"Fahrenheit Value!"

message:soapResults

delegate:self

cancelButtonTitle:@"OK"

otherButtonTitles:nil];

[alert show];

resultLabel.text=soapResults;

//[alert release];

[soapResults setString:@""];

elementFound = FALSE;

}

}

May 25, 2012 8:48 PM in response to munna1116

Glad you got it working. If you will be making a lot of differnet SOAP requests, or if the SOAP response has lists of items or multiple values, I recommend using an XML DOM rather than an XML parser. NSXMLDocument is not supported on iOS so you must use a 3rd-party library like Google's GDataXMLDocument. The following example shows how easy this is to use.


- (void)connectionDidFinishLoading:(NSURLConnection *)connection

{

// stuff response into XML doc

NSError *error = nil;

GDataXMLDocument *responseXml = [[GDataXMLDocumentalloc] initWithData:responseDataoptions:0error:&error];

if (error) {

[NSExceptionraise:@"connectionDidFinishLoading error"format:error.localizedDescription];

}

// query value

NSDictionary *namespaces = [NSDictionarydictionaryWithObjectsAndKeys:@"http://tempuri.org/", @"def", @"http://www.w3.org/2003/05/soap-envelope", @"soap", nil];

NSArray *resultNodes = [responseXml nodesForXPath:@"soap:Envelope/soap:Body/def:CelsiusToFahrenheitResponse/def:CelsiusToFahrenhei tResult"namespaces:namespaces error:&error];

if (error) {

[NSExceptionraise:@"connectionDidFinishLoading error"format:error.localizedDescription];

}

// update user interface

if (resultNodes.count > 0)

resultLabel.text = [[resultNodes objectAtIndex:0] stringValue];

else

resultLabel.text = @"";

}

May 26, 2012 1:54 AM in response to munna1116

As of now i am returning only single value, so i have used XML parsing, may be in future may be returning multiple values will come that time i am sure it will be very helpfull for me.

Thank you so much.

Mr. Llessur999 i have one problem regarding tracking the current location when the app is running (with the intervals of every 10 mins.). I have posted my problem in the discussion but till now i did not get any proper response about it. Please help me.

Thank u.


Jun 24, 2012 5:02 AM in response to munna1116

Hi Mr. Llessur999,


Thnx to you for the above post.


I am using the same code as above for consuming webservice but if the value returns by one of methods of the webservice is string then I get error but if it is integer then it works fine.


Would you please tell me what to change in the above code to get string value?


Thanx in advance.


Regards


Faheem

Oct 5, 2012 2:22 PM in response to forall02

If this is a SOAP web service, you include all parameters in the SOAP envelope that you POST as the request. The envelope format for each operation is described in the service WSDL. Some SOAP endpoints allow GETs with parameters defined in the querystring.


If this is something other than SOAP, for example one of the many REST variants, there is no standard request format so you must consult the documentation for the service. But the same concept applies, parameters are defined in the request body (often JSON) for POST or the querystring for GET.

Oct 12, 2012 6:03 AM in response to munna1116

Hi Munna1116,


I am also working with the same kind of SOAP web service. Your code example looks very perfect, but for some reason I am getting and error as

'NSInvalidArgumentException', reason: '-[__NSCFString setLength:]: unrecognized selector sent to instance 0x68b9b30'.

In

-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response

{

[responseDatasetLength: 0];

}


Could you kindly help me to look your code. It could be of great help. My email id is alarshad2007@yahoo.com.


Thanks a lot in advance.

Oct 12, 2012 8:55 AM in response to alarshad

NSInvalidArgumentException', reason: '-[__NSCFString setLength:]: unrecognized selector sent to instance 0x68b9b30'.

Verify that responseData is defined as NSMutableData. Based on the error message, it looks like you incorrectly defined responseData as NSString or NSMutableString.


Could you kindly help me to look your code. It could be of great help.

The code sample in the second post is complete. Just create a storyboard view with label/text fields corresponding to the two IBOutlets, and a button for the IBAction.

How to consume SOAP web service by passing parameters through Xcode 4.3

Welcome to Apple Support Community
A forum where Apple customers help each other with their products. Get started with your Apple ID.