Wednesday, August 25, 2010

Calling WCF Service from your I PAD/ i Phone Application (Objective C)

Last Days i have been assigned a task to call an WCF service from an I PAD Application. For all the .Net Programmers this thing is quite simple just to add a reference and Job's done but its not that simple in Objective C we need to create a raw request and then a get a Response. Yet again the response is in raw format as well so we need to do some parsing on it as well.

Again the Tool that helped me lot is Fiddler. As you know that asmx service request and response can easily be obtained by just opening the service URL in browser but its not the case with WCF service you need to create request by your self.

In order to make the job simpler and understandable i used two things


  • Call the Web service in a c# web application and check all the parameters that it accepts. so that you get an idea of what needs to be sent in request

  • Secondly Open up fiddler and run the web application so that we can get the Request XML that is created when calling the web service

So we are done with the Environment part now lets start some Objective C portion.

First Create a simple View based application. open the Xib file of view controller place a button over there.

Navigate to the header file of view controller create an Outlet and an IBAction. Then register that action to the button.

Now we come to the .M file of view controller, suppose the function name was buttonClicked we create a string in that and paste the Request from fiddler with little modifications in that.

Note that i have passed three types of parameters to the Request
1. Array of String
2. Boolean
3. Integer Value


Also You will notice two tags
FUNCTION_NAME
PARAMETER_NAME

These two tags specify the function to be called from service and the list of parameters that is passed in this case i have passed a complex type parameter which contains from other normal parameters.



-(IBAction) buttonClicked:(id)sender{
 
 
 NSString *soapMsg = [NSString stringWithFormat:
       @"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
       "<SOAP-ENV:Envelope \n"
       "xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" \n"
       "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" \n" 
       "xmlns:SOAP-ENC=\"http://schemas.xmlsoap.org/soap/encoding/\" \n"
       "SOAP-ENV:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\" \n"
       "xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\"> \n"
       "<SOAP-ENV:Body> \n"
       "<FUNCTION_NAME xmlns=\"http://tempuri.org/\">"
       "<PARAMETER_NAME xmlns:a=\"http://schemas.datacontract.org/2004/07/BBB.Model\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">"
       "<a:_x003C_BrandName_x003E_k__BackingField i:nil=\"true\" xmlns:b=\"http://schemas.microsoft.com/2003/10/Serialization/Arrays\"/>"
       "<a:_x003C_DisplayOnWeb_x003E_k__BackingField>false</a:_x003C_DisplayOnWeb_x003E_k__BackingField>"
       "<a:_x003C_IsFeatured_x003E_k__BackingField>false</a:_x003C_IsFeatured_x003E_k__BackingField>"
       "</PARAMETER_NAME>"
       "</FUNCTION_NAME> \n"
       "</SOAP-ENV:Body> \n"
       "</SOAP-ENV:Envelope>"];
 
 
 //NSLog(soapMsg);
 NSURL *url = [NSURL URLWithString: @"http://SERVICE_URL/Service.svc"];
 NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:url];
 
 NSString *msgLength = [NSString stringWithFormat:@"%d", [soapMsg length]];
 [req addValue:@"text/xml; charset=utf-8" forHTTPHeaderField:@"Content-Type"];
 [req addValue:@"http://tempuri.org/ICommerceService/FUNCTION_NAME"
   forHTTPHeaderField:@"SOAPAction"]; 
 [req addValue:msgLength forHTTPHeaderField:@"Content-Length"];
 //---set the HTTP method and body--- 
 [req setHTTPMethod:@"POST"]; 
 [req setHTTPBody:[soapMsg dataUsingEncoding:NSUTF8StringEncoding]];
 conn = [[NSURLConnection alloc] initWithRequest:req delegate:self]; if (conn) {
  webData = [[NSMutableData data] retain];
 }
 
}

-(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 {
 [webData release]; 
 [connection release];
}

-(void) connectionDidFinishLoading:(NSURLConnection *) connection { 
 
 NSLog(@"DONE. Received Bytes: %d", [webData length]);
 NSString *theXML = [[NSString alloc]
      initWithBytes: [webData mutableBytes] 
      length:[webData length] 
      encoding:NSUTF8StringEncoding];
 //---shows the XML--- 
 //NSLog(theXML);
 [theXML release];
 [connection release];
 [webData release];
}

The function will give the response in connectionDidFinishLoading which can then be parsed by any XML parser.

The Best XML parser that i found is COCOA With Love.

Hope It Helps.

Happy Coding....

3 comments:

Unknown said...

Hi, I have a problem with a WCF service. I need to pass as parameter, a table with various rows and columns, like this: , where the TABLE1 tag can repeat 2 or 3 times. How can I write this in the request?

Unknown said...

sorry, the example not appear: <PARAM1><TABLE1><FIELD1></FIELD1><FIELD2></FIELD2></TABLE1></PARAM1>

Unknown said...

how to pass string array as a parameter?? can just show some code example?? thanx in advance