SOAP based WebServices integration in an iOS app
This post describes how to invoke a SOAP based web service from your iOS app. The post is not going to dwell into the discussion of SOAP based versus a RESTful service and neither is it intended to be a tutorial on SOAP. For more information on the latter,there are plenty of online resources including the W3C (http://www.w3.org/TR/soap/). This post assumes that your needs require invocation of SOAP based web services from your iOS app.
We will use a free online web service http://www.webservicex.net/CurrencyConvertor.asmx?WSDL for our example. This is a very simple web service handles currency conversions (surprise!).
I recommend a free utility called "wsdl2objc" which generates client-side Objective-C code from a SOAP Web Services Definition File (WSDL) file. You can always construct the SOAP request messages and parse the SOAP responses on your own without the tool, however, the tool does a lot of the heavy lifting and is convenient.
1. Download the wsdl2objc tool from http://code.google.com/p/wsdl2objc/
2. Run the wsdl2objc tool . Enter the source URL for the WSDL and the destination folder for the generated ObjC files and select "Parse WSDL" button. A screenshot of the same is shown below
3. Once the "Parse WSDL" process completes, you should see a number of ObjC files in the destination folder.
4. Follow the following steps to integrate the ObjC files into your app.
4a) Copy the ObjC files that were generated in the previous step to your app project. Make sure you select the "Copy Files Into Destination Folder" option.
4b) If you are using ARC in your project, you will have to disable ARC for the generated ObjC files. To do this, go to the "Compile Sources" section of "Build Phases" of your project and specify the "-fno-objc-arc" compiler flag for all the generated files.
4c) If you already have libxml2 installed on your system (look for libxml2.dylib in /usr/lib folder), then skip this step. Otherwise, follow the steps in (4c) to install libxml2 library
4c-1) Install the macports package installer from http://www.macports.org/install.php (if you don't have it already)
4c-2) Install libxml2 library by executing the following command in a terminal window
sudo port install libxml2
(*Tip* For the build to work for libxml2, make sure you have the command line tools installed for Xcode )
4d) In the target "Build settings", include "-lxml2" in the "Other Linker Flags" property
4e) In the target "Build settings", include "$(SDKROOT)/usr/include/libxml2" in the "Header Search Paths" property
4f) Import "CurrencyConvertorSvc.h" file into your implementation file and use the methods provided by this interface to make the appropriate web services calls.
The following code snippet demonstrate its usage
1 |
-(void)processRequest
{
CurrencyConvertorSoapBinding* binding = [CurrencyConvertorSvcCurrencyConvertorSoapBinding];
CurrencyConvertorSoapBindingResponse* response;
CurrencyConvertorSvc_ConversionRate* request = [[CurrencyConvertorSvc_ConversionRatealloc]init];
request.FromCurrency = CurrencyConvertorSvc_Currency_enumFromString(self.fromCurrencyTextField.text);
request.ToCurrency = CurrencyConvertorSvc_Currency_enumFromString(self.toCurrencyTextField.text );
response = [binding ConversionRateUsingParameters:request];
dispatch_async(dispatch_get_main_queue(), ^{
[self processResponse:response];
});
}
1 |
-(void) processResponse: (CurrencyConvertorSoapBindingResponse*)soapResponse
{
NSArray *responseBodyParts = soapResponse.bodyParts;
id bodyPart;
[self.activitystopAnimating];
[self.activityremoveFromSuperview];
@try{
bodyPart = [responseBodyParts objectAtIndex:0]; // Assuming just 1 part in response which is fine
}
@catch (NSException* exception)
{
UIAlertView* alert = [[UIAlertViewalloc]initWithTitle:@"Server Error"message:@"Error while trying to process request"delegate:selfcancelButtonTitle:@"OK"otherButtonTitles: nil];
[alert show];
return;
}
if ([bodyPart isKindOfClass:[SOAPFault class]]) {
NSString* errorMesg = ((SOAPFault *)bodyPart).simpleFaultString;
UIAlertView* alert = [[UIAlertViewalloc]initWithTitle:@"Server Error"message:errorMesg delegate:selfcancelButtonTitle:@"OK"otherButtonTitles: nil];
[alert show];
}
elseif([bodyPart isKindOfClass:[CurrencyConvertorSvc_ConversionRateResponseclass]]) {
CurrencyConvertorSvc_ConversionRateResponse* rateResponse = bodyPart;
UIAlertView* alert = [[UIAlertViewalloc]initWithTitle:@"Success!"message:[NSStringstringWithFormat:@"Currency Conversion Rate is %@",rateResponse.ConversionRateResult] delegate:selfcancelButtonTitle:@"OK"otherButtonTitles: nil];
[alert show];
}
}
An example project can be downloaded from the following link- SOAP Test. The project has been built using Xcode 4.5.
32 comments
Trackback e pingback
No trackback or pingback available for this article
Thanks for this really nice tutorial on using wsdl2objc !!
However, i am facing a couple of issues. Would be great if you could probably guide me through..
Every time in my processResponse function, my responseBodyPart is of type SOAPFault. My server is up and running and the wsdl link shows the xml correctly.
Can you possibly help me figure out why am i always running into SOAPFault ?
Thanks,
Ankit 🙂
just to add, the exception details are:
“Server Error”
“Exception occurred while trying to invoke service method xxx”
Glad you found the tutorial useful. Seems like a issue with the response from the server. My suggestion would be to use soapUI (http://www.soapui.org) to issue the requests and test it out.
hi,
i am fresher for iphone developer.
i don’t know what is web server and how use web server, and why are used web server, if don’t mine could you tell me the answers of my questions. please give me sufficient tutorial for me please please please
my email id: galaba.sivaprasad63@gmail.com
You may want to check out the basics of web services at http://en.wikipedia.org/wiki/Web_service. Web services itself has nothing to do with iOS development. You need to identify what your app requirements are in order to determine whether there is a need for backend web service to service the app.
Hello Admin,
Your article has been really helpful for me throughout. However, I am long stuck on an issue with my web services, which is going beyond my trace. I would be thankful to you, if you could possibly share the backend webservices written for the above example- CurrencyConverter.
Much Thanks,
Ankit
Hi Ankit
The current converter is a free web service that is available at http://www.webservicex.net/ws/default.aspx. I did not implement it. Also, I would recommend using SOAP UI tool for testing your web services SOAP interface manually .
Good Luck!
Is this tool work for authenticated webservices also? Then how to provide Username and Password.
Thanks for the Tutorial
You would need to define an API in your WSDL that takes in user name and password as input parameters and your web service should implement the authentication logic. This tool is used for generating objective C client side stub code from WSDL- It is essentially a SOAP message generation tool. it is agnostic of what the web services does .
i had used http://service.taxdatasystems.net/TdsBasic.svc?WSDL to get tax information in iOS but i am getting an error which i am unable to solve .please figure me out
2013-03-02 17:05:21.355 ShowTaxDetails[6157:11303] OutputHeaders:
{
“Content-Length” = 743;
“Content-Type” = “text/xml; charset=utf-8”;
Host = “service.taxdatasystems.net”;
SOAPAction = “http://tempuri.org/ITdsBasic/GetTDSBasicUSPlainNetwork”;
“User-Agent” = wsdl2objc;
}
2013-03-02 17:05:21.357 ShowTaxDetails[6157:11303] OutputBody:
90001
xxx@gmail.com
xxxx
2013-03-02 17:05:21.361 ShowTaxDetails[6157:11303] here response=(null)
2013-03-02 17:05:22.581 ShowTaxDetails[6157:11303] ResponseStatus: 500
2013-03-02 17:05:22.581 ShowTaxDetails[6157:11303] ResponseHeaders:
{
“Content-Length” = 734;
“Content-Type” = “text/xml; charset=utf-8”;
Date = “Sat, 02 Mar 2013 11:30:16 GMT”;
Server = “Microsoft-IIS/7.0”;
“X-Powered-By” = “ASP.NET”;
}
2013-03-02 17:05:22.582 ShowTaxDetails[6157:11303] ResponseBody:
a:InternalServiceFaultThe server was unable to process the request due to an internal error. For more information about the error, either turn on IncludeExceptionDetailInFaults (either from ServiceBehaviorAttribute or from the <serviceDebug> configuration behavior) on the server in order to send the exception information back to the client, or turn on tracing as per the Microsoft .NET Framework 3.0 SDK documentation and inspect the server trace logs.
2013-03-02 17:05:42.008 ShowTaxDetails[6157:11303] here soapresponse=
2013-03-02 17:05:46.695 ShowTaxDetails[6157:11303] responseheasred=(null)
2013-03-02 17:05:49.901 ShowTaxDetails[6157:11303] bodyparts=(
)
2013-03-02 17:05:51.222 ShowTaxDetails[6157:11303] idpart=(null)
Great tutorial!
By referring to this tutorial, I’ve created a similar tutorial here, using a tool called Pico, Pico is a web service client framework targeting iOS platform, it provides code generator tool based on Java Wsimport, also it provides a runtime which can automatically bind soap message with object model, Pico has been verified with industrial level wsdl like amazon and ebay wsdl. you may have a try if you are interested.
Thanks! Will check out Pico sometime.
Hii admin,
I am using WCF web service to communicate with iPhone app.
I have used the tool provided in the article to convert the wsdl to objectiveC. After adding the the objc files created after converting, I am not able to access the SOAP apis , instead i am able to access corresponding BasicHttpBinding APIs like “BasicHttpBinding_IService1Response”.
Also, the result obtained “responseBodyParts” is null.
Can you please provide a solution !
hi.thanks for help about webservices.now my ask about data migration.How do we move the data between two view when from the web service response.but i dont want to use preparesegue() method.
Hi Murat
There are lots of ways to handle that . If you don’t want to pass the data via the prepareforsegue call (not sure why you wouldn’t want to do that), then having a global data manager (singleton class) to store the web services response is probably the simplest approach. This would then be accessible from all view controllers. You could also store the response data in a local DB store (sql lite).
Could wsdl2objc support HTTPS connection ?
Thanks.
Hi Yita
The tool independent of the transport (HTTP or HTTPS) and it is not concerned with how the web service is accessed.
It’s not working properly
I used the tool to convert the wsdl but get this error when i consume the service.
Error:Thread 1:EXE_BAD_ACCESS (code=2,address=0xc)
else if (xmlStrEqual(bodyNode->ns->prefix, (const xmlChar *) “soap”) &&
xmlStrEqual(bodyNode->name, (const xmlChar *) “Fault”)) {
This is how i called the method
fitBindingResponse* cal=[binder CalculateQuoteUsingQuoteData:newQuote];
could this be an authentication issue on the server?
The error Occurred inside method
– (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
This is great tutorial,
i’m using wsdl2objc like this tutorial. but my iOS client can’t call with parameter. my parameter is null on web service method. so can get return parameter on iOS client. why my request parameter is null on web service method.
any luck?
I have used wsdl2objc for http://ncga.elasticbeanstalk.com/services/v1/APIMethodsService?wsdl
code is
APIMethodsImplServiceSoapBinding* binding = [APIMethodsImplService APIMethodsImplServiceSoapBinding] ;
binding.authUsername=@”ncgaUser3#”;
binding.authPassword=@”ncgaPassword3!”;
binding.logXMLInOut=YES;
binding.address=[NSURL URLWithString:@”http://ncga.elasticbeanstalk.com/services/v1/APIMethodsService?wsdl”];
APIMethodsImplService_findGolfer* request = [[APIMethodsImplService_findGolfer alloc]init];
request.ghinNumber=[NSNumber numberWithInt:1234567];
NSLog(@”REQUIEST IS %@”,request);
APIMethodsImplServiceSoapBindingResponse* response=[binding findGolferUsingParameters:request];
dispatch_async(dispatch_get_main_queue(), ^{
[self processResponse:response];
});
But unfortunately i got error
fault msg is Unmarshalling Error: unexpected element (uri:”http://api.service.ncga/”, local:”ghinNumber”). Expected elements are
Please suggest where i am wrong.
Thanks in Advance.
The article seems to be very good. However, when I run the tool, nothing is getting created in the destination folder. Is there a problem with the tool?
Thus , I’m unable to proceed further.
Thanks a lot!!
There has been lot of spaces has been lost which can run a new bibe like me in to problems. Here is one example
CurrencyConvertorSoapBinding* binding = [CurrencyConvertorSvcCurrencyConvertorSoapBinding]; must be
CurrencyConvertorSoapBinding* binding = [CurrencyConvertorSvc CurrencyConvertorSoapBinding];
DEAR SIR
i am new in iOS development.your demo is working properly but i found it defecult in my application
i have one web service name “ws” and it have a class name “hello world” calling hello world return time
i dont understand how to call it
please help
Hi Priya,
Great tutorial, but i am facing one issue. I am able to proceed successfully till step “4c-1”, but after that having installed Command line tools also i am unable to install “libxml2” from terminal. I am using xcode 4.6.3 on mac 10.7. Any suggestions would be of great help.
Thank you in advance.
CurrencyConvertorSoapBinding not found
I think now it’s CurrencyConvertorSoap
In latest version MacOS Sierra its not opening the application
I got the below error
You can’t use this version of the application “WSDL2ObjC” with this version of macOS.
earlier i used terminal command for generating stubs class for the WSDL converstion into Objective-C class, but now I forgot that command Hope your team familar with same can you assist me for generating the stubs class or any latest wsdl2obj tool avaiable ?