Saturday, December 25, 2010

Handling SOAP with iPhone

Hi All,

I am writing this blog to help you all in Parsing XML(SOAP) response.
In coming sections I'm gonna give you basic steps to parse XMLResponse and later with some extremely useful links to make your work a piece of cake when it comes to handling SOAP in iPhone.

Basic Steps (This are the steps needs to be done while sending request and parsing XMLResponse) :


//Sending Request

NSURL *url = [NSURL URLWithString:@"https://servername.com/WebService/WebServicename.asmx"];
NSMutableURLRequest *theRequest = [NSMutableURLRequest requestWithURL:url];
NSString *msgLength = [NSString stringWithFormat:@"%d",[soapMessage length]];
[theRequest addValue:@"text/xml" forHTTPHeaderField:@"Content-Type"];
[theRequest addValue:@"servername.com/Hello" forHTTPHeaderField:@"SOAPAction"];
[theRequest addValue:msgLength forHTTPHeaderField:@"Content-Length"];
[theRequest setHTTPMethod:@"POST"];
[theRequest setHTTPBody:[soapMessage dataUsingEncoding:NSUTF8StringEncoding]];
NSURLConnection *theConnection = [[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
if(theConnection)
webData = [[NSMutableData data] retain];
//here webdata is => NSMutableArray *webdata; 
else 
NSLog(@"theConnection is null");
//At this point connection is setup and delegate is set to self, now is time to use connection delegate methods. Four methods that we gonna use:

-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
[webData setLength:0];
}

-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[webData appendData:data];
}

-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{
NSLog(@"Error with connection %@",error);
[connection release];
[webData release];
}
-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSLog(@"Done. received Bytes %d", [webData length]);
NSString *theXML = [[NSString alloc] initWithBytes:[webData mutableBytes] length:[webData length] encoding:NSUTF8StringEncoding];
[theXML release];
//xmlparser declared in header as => NSXMLParser *xmlparser

if(xmlParser)
{
[xmlParser release];
}
xmlParser = [[NSXMLParser alloc] initWithData:webData];
[xmlParser setDelegate:self];
[xmlParser setShouldResolveExternalEntities:YES];
[xmlParser parse];
 
[connection release];
[webData release];
}


  • //Now we will start of XMLParsing as we have response needed.

This method is to check start of elements. 
If element is equal to "Result", set BOOL (recordResults) to true, and initialize the MutableString (soapResults):
-(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName attributes:(NSDictionary *)attributeDict
{
if([elementName isEqualToString:@"Result"])
{
if(!token)
{
soapResults = [[NSMutableString alloc] init];
}
recordResults = TRUE;
}
}

//This method is to store the result between element (Result):
-(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{

if(recordResults)
{
[soapResults appendString:string];
}

//NSLog(@" soap: %@", soapResults);
}

//This third method where we will look for end element (Result in our case), here you may/can do some changes and format your result you want it to handle.

-(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName 
{
if([elementName isEqualToString:@"Result"])

{
if(!token)
{
token = [[NSString alloc] initWithString:soapResults];
NSLog(@"auth1 token: %@",token);
}
        //Do Something with result here

recordResults = FALSE;
[soapResults release];
soapResults = nil;
}
}



I have given you basics of XML request and parsing so far, from this point if your programming skill are good can manage to handle any response.

But for those and also in real application mostly XMLResponse are not that easy to read and analyze to our needs. To do that I have come through some useful links and work done by others to make our job easier, I am posting those links with some information about them, you can choose link of your choice.
  • Sudzc
It has all, just give your web service link to the site, they will generate request and response handler for all web services method on that address and a simple tutorial to explain how to use it. 
Straightforward work, excellent for newbies and who dun want to waste their time writing code.


  • wsdl2objc

Its another approach,  not recommended ny me and many others.

  • In case response you getting is like:<Menus>
    <Table1>
    <Restaurant_Name>CHICK-FIL-A</Restaurant_Name>
    <Restaurant_id>2748</Restaurant_id>
    <billing_city>DECATUR</billing_city>
    <billing_state>GA</billing_state>
    </Table1>
    </Menus>

    I have done some work to handle this response according to my need, if needed can ask me will provide help in handling this response.
Please feel free to ask and comment your view.

Thanks
AB