Home > Programming, iPhone > Using .NET web services and dataset objects in your iphone app

Using .NET web services and dataset objects in your iphone app

iPhone XML SOAP or .NET Web Services

can seem overwhelming at first but its actually not too hard to do, you can even download a .NET dataset and query it on the iPhone!

Being a complete n00b to iphone’s cocoa touch api / objective C and then jumping in feet first to iphone programming is like being swallowed by an enormous whale. Its very dark, you can see the blow hole, but you know the only way of reaching it is to be blown out by a mucous-infused geisure of  hot and sticky whale snot. (if you have ever tried to obtain help on irc or various forums you know what I am talking about) not to mention the endless sea of apple docs that may or may not contain any information that you actually need depending on your luck.

That being said after much hair pulling reading docs forums and some examples from everywhere I have put together a simple solution to connect to a .NET web service over https and return a dataset object back to the iphone that can be queried and used accordingly.

Download This: iPhone .NET Dataset Framework.zip

In the attached file you will find 6 documents:

DataSet.h
DataSet.m
XMLDataSetParser.h
XMLDataSetParser.m
WebServiceHelper.h
WebServiceHelper.m

These files are pretty much self explanatory. DataSet.h/.m contain code for creating your DataSet Object and contain methods for querying the dataset.

WebServiceHelper contains the code to connect to the appropriate web service with the appropriate methods and parameters

XMLDataSetParser will take the data received from the webservice and pipe it into your DataSet Object.

To use an XML .NET Web service all you need to do is include these files in your project and then call the following procedures.

//First import the relevant files to your viewcontroller class (XMLDataSetParser is
//included by the DataSet class so there is no need to import it here)

#import "WebServiceHelper.h"
#import "DataSet.h"

// Create a connection to the web service
WebServiceHelper *DataCon = [[WebServiceHelper alloc] init];
//set up service method and urls please visit the webservice address in a browser to
//get the exact strings the service expects

DataCon.XMLNameSpace = @"https://myurl.com/WebService";
DataCon.XMLURLAddress = @"https://myurl.com/WebService/service.asmx";
DataCon.MethodName = @"getDataSetFromServer";

//add parameters **PARAMETERS ARE CASE SENSITIVE MAKE SURE THEY ARE TYPED CORRECTLY
//AS THE SERVICE EXPECTS THEM**

DataCon.MethodParameters = [[NSMutableDictionary alloc] init];
[DataCon.MethodParameters setObject:@"Parameter1" forKey:@"P1"];
[DataCon.MethodParameters setObject:@"Parameter2" forKey:@"P2"];

//Connect to the service and retrieve the xml raw data into a NSMutableDataObject
//be sure to include a NSMutableData object called "data" or whatever you wish in
//your viewcontroller

self.data = [DataCon initiateConnection];

//Create a dataset object using the new raw data we received from the service
DataSet *dsMyDataSet = [[DataSet alloc] initWithXMLData:self.data];

//Now we have a dataset filled with data from the initWithXMLData command lets
//query some data from it!
//Set up a dictionary object to hold our query data from the dataset

NSMutableDictionary *mydata= [[NSMutableDictionary alloc] init];

//retrieve all rows from the selected table and column
mydata = [dsMyDataSet getRowsForTableAndColumn:@"Table1" col:@"Username" ];
//mydata should contain all rows from column "Username"

//retrieve all rows from the selected table and column where the CURRENT column
//matches a string

mydata = [dsMyDataSet
getRowsForTableAndColumnWhereEqualsString:@"Table1" col:@"username" where:@"bob"];
//mydata should contain all rows from column username containing the exact match "bob"

//retrieve all rows from the selected table and column where a DIFFERENT column
//matches a string

mydata = [dsMyDataSet
getRowsForTableAndColumnWhereColumnEqualsString:@"Table1"
col:@"username" whereColumn:@"email" whereValue:@"bob@microsoft.com"];
//mydata should contain all rows from column "username" where the column "email"
//contains the exact match "bob@microsoft.com"

//you can do what you want with the data at this point like a simple iteration
NSEnumerator *userIterator= [mydata objectEnumerator];

NSString *username;

while(username =  [userIterator nextObject])
{
NSLog(@"Username: %@", username);
}
[mydata release];

Thats it!!! Hope this helps someone else save as much time as it is now saving me!

Categories: Programming, iPhone
  1. November 8, 2009 at 8:54 am | #1

    Hi,

    I was just wondering what self.data is defined as within the interface.

    Regards
    Mick

    • o0joecool0o
      November 8, 2009 at 6:00 pm | #2

      self.data is just an NSMutableData object to hold the raw data returned from the XML service, it can be defined in your function or in the view controller interface, I sometimes access this object from outside the view controller and that is why I chose to declare it inside the interface. Your application may or may not have this requirement.

  2. November 18, 2009 at 12:20 pm | #3

    Nice post & nice blog. I love both.

  3. ekkk
    December 14, 2009 at 10:49 am | #4

    Hi,

    I have a problem to pass the parameters from conn.method (Iphone) to .NET Web Services, using below codes.

    //add parameters **PARAMETERS ARE CASE SENSITIVE MAKE SURE THEY ARE TYPED CORRECTLY
    //AS THE SERVICE EXPECTS THEM**
    DataCon.MethodName = @”getDataSetFromServer”;
    DataCon.MethodParameters = [[NSMutableDictionary alloc] init];
    [DataCon.MethodParameters setObject:@"Parameter1" forKey:@"P1"];
    [DataCon.MethodParameters setObject:@"Parameter2" forKey:@"P2"];

    I created a Web Services Method ,getDataSetFromServer(string P1, string P2)
    to get parameters from Parameter1, Parameter2 ,
    but I receive nothing subsequently.

    What’s the reason why? Wait for your reply!

    Regards,

    Ekkk

    • o0joecool0o
      December 15, 2009 at 4:29 am | #5

      I would need more information if you would like to send me the relevant files you can email them to me and I would be happy to look over the code and see if I can find the error. The above parameter info looks correct so I suspect the error is somewhere else perhaps the connection URL or the receiving NSMutableData array. I will email you at the address you specified for your post so you can reply

  4. jason
    December 21, 2009 at 7:07 pm | #6

    How would I populate a table with this data I am a noobie.

    • o0joecool0o
      December 23, 2009 at 3:49 pm | #7

      You can populate a table using the same code, in a tableview the function “cellForRowAtIndexPath” you would simply add the cell.text as the object at that indexPath.
      NSUInteger row = [indexPath row];

      cell.text = [mydata objectAtIndex:row];

  5. Billy
    December 21, 2009 at 10:50 pm | #8

    Great article, what code changes need to be made in order for this to work with none ssl web service?

    • o0joecool0o
      December 23, 2009 at 3:51 pm | #9

      under WebserviceHelper.m I believe you just need to comment out the line

      [NSURLRequest setAllowsAnyHTTPSCertificate:YES forHost:[myWebserverURL host]];

  6. Shibin
    December 23, 2009 at 5:34 am | #10

    Thanks for the post..

    But i am not using a data-set. i am retrieving a simple XML file. how can i change this to implement my changes.

    Thanks in advance. please help.

    • o0joecool0o
      December 23, 2009 at 3:53 pm | #11

      You can use the “WebServiceHelper.m” object to make your connection and modify the XMLDataSetParser to conform to your own XML structure that you are receiving. Or just use it as an example to create your own XML parser using the Objective C NSXMLParser object.

  7. Steve
    December 24, 2009 at 6:47 am | #12

    Do you know if there is any way to get the details of the webservice if all you have been provided with is the .svc file and not the asmx details? This is fine under .Net where you can connect to the service and then find the underlying functions, but I can’t seem to find anything that describes how to do the same thing for iPhone.

  8. December 29, 2009 at 9:38 am | #14

    Calling a web method (without parameters) its ok, but when I called my web service method passing in parameter, it don’t seems to work.
    Hopefully theres some tutorial on this as well as how the web service method look like in C#.
    Not sure if the parameter is to be passed like the following:

    //add parameters **PARAMETERS ARE CASE SENSITIVE MAKE SURE THEY ARE TYPED CORRECTLY
    //AS THE SERVICE EXPECTS THEM**
    DataCon.MethodParameters = [[NSMutableDictionary alloc] init];
    [DataCon.MethodParameters setObject:@"npalmtest" forKey:@"strUserID"];

    • o0joecool0o
      December 29, 2009 at 3:23 pm | #15

      vb and C should make no difference the web service is still a soap service with standard parameters. Make sure when you connect to the .asmx url you are seeing the .net web method and parameters typed properly and case sensitive.

  9. December 29, 2009 at 9:45 am | #16

    i wonder issue #4 has been resolved, i had the exact same problem.

    • o0joecool0o
      December 29, 2009 at 3:24 pm | #17

      issue #4 turned out to be an issue using special characters in the data that interfered with xml structure.

      • ekkk
        December 31, 2009 at 1:55 am | #18

        How to solve if I using special characters in the data ??

        I haved been implemented into encoding uft-8 in XML structure

        Thanks and Regards,

  10. coco
    December 29, 2009 at 10:27 pm | #19

    I am not sure what I am doing wrong, but … I tried this example … and I am having an issue with the declaration of self.data. I have pasted the code for the use in the ViewController.m page inside the viewDidLoad method. I’ve tried a few different ways but I still see no data coming out.

    Looks like this:


    DataCon.XMLNameSpace = @”http://www.webservicex.net/”;
    DataCon.XMLURLAddress = @”http://www.webservicex.net/uszip.asmx”;
    DataCon.MethodName = @”GetInfoByCity”;

    //add parameters **PARAMETERS ARE CASE SENSITIVE MAKE SURE THEY ARE TYPED CORRECTLY
    //AS THE SERVICE EXPECTS THEM**
    DataCon.MethodParameters = [[NSMutableDictionary alloc] init];
    [DataCon.MethodParameters setObject:@"New York" forKey:@"USCity"];
    //[DataCon.MethodParameters setObject:@"Parameter2" forKey:@"P2"];

    //Connect to the service and retrieve the xml raw data into a NSMutableDataObject
    //be sure to include a NSMutableData object called “data” or whatever you wish in
    //your viewcontroller
    //NSMutableData *data;//=[[NSMutableData alloc] retain];

    //self.data = [NSMutableData data]
    self.data = [DataCon initiateConnection];

    //Create a dataset object using the new raw data we received from the service
    DataSet *dsMyDataSet = [[DataSet alloc] initWithXMLData:data];

    what I get is that data is something not a union or structure. Thank you in advance.

    • Luis Enrique Ortiz
      December 30, 2009 at 1:18 am | #20

      you have to declare self.data in the header
      example:

      @interface TestWSViewController : UITableViewController{
      NSMutableData *data;
      }

      @property(nonatomic, retain) NSMutableData *data;

      @end

      and then in the implementation

      @implementation TestWSViewController

      @synthesize data;

  11. Luis Enrique Ortiz
    December 29, 2009 at 10:28 pm | #21

    i have the same error in the parameters, i get “” in the reveiving parameters in the web service

    i have
    _
    Public Function obtenerVentas(ByVal fecha As String) As DataSet

    and in the iphone app i have

    WebServiceHelper *DataCon = [[WebServiceHelper alloc] init];
    DataCon.XMLNameSpace = @”http://leortiz-imac/irrab”;
    DataCon.XMLURLAddress = @”http://leortiz-imac/irrab/ventas.asmx”;
    DataCon.MethodName = @”obtenerVentas”;

    DataCon.MethodParameters = [[NSMutableDictionary alloc] init];
    [DataCon.MethodParameters setObject:@"12/01/2009" forKey:@"fecha"];
    self.data = [DataCon initiateConnection];

    • coco
      December 29, 2009 at 10:42 pm | #22

      How do you initialize the self.data variable?

    • December 30, 2009 at 2:45 am | #23

      My problem is exactly similar to this. The following is a snippet code:

      self.data = [[NSMutableData alloc] init];
      WebServiceHelper *DataCon = [[WebServiceHelper alloc] init];
      DataCon.XMLNameSpace = @”http://tempuri.org”;
      DataCon.XMLURLAddress = @”http://192.168.0.20/uploadlinkservice/service1.asmx”;
      DataCon.MethodName = @”GetUsers”;
      DataCon.MethodParameters = [[NSMutableDictionary alloc] init];
      [DataCon.MethodParameters setObject:@"npalmtest" forKey:@"strUserID"];
      self.data = [DataCon initiateConnection];

      while the C# web service method looks like this:

      [WebMethod(Description = "Returns NPalmDB users", EnableSession = true)]
      public DataSet GetUsers(String strUserUD)
      {
      SqlConnection con = new SqlConnection(con);
      if (strUser == “npalmtest”) {
      SqlDataAdapter DA = new SqlAdapter(“Select * from Users, con);
      DataSet DS = new DataSet();
      DA.Fill(DS,”Users”);
      return DS;
      }
      else
      return null;
      }

      Problem is nothing gets passed into the webservice parameters..

    • December 30, 2009 at 2:55 am | #24

      And after printing the sRequest, all seems correct, only the parameter “npalmtest” does not parse into the strUserID param.

      Printing description of sRequest:
      npalmtest

    • December 30, 2009 at 2:56 am | #25

      Printing description of sRequest:
      npalmtest

    • December 30, 2009 at 2:58 am | #26

      Printing description of sRequest:
      //npalmtest

    • o0joecool0o
      December 30, 2009 at 3:27 pm | #27

      the functions I wrote utilize the windows .NET service methods. I see you are connecting to an imac so I am not sure what you are using for a web service. My dataset methods parse .NET specific tags and attributes to determine where the tables and rows start in the xml structure.

  12. Luis Enrique Ortiz
    December 30, 2009 at 1:15 am | #28

    when i want to populate a TableView with

    NSUInteger row = [indexPath row];

    cell.text = [mydata objectAtIndex:row];

    i get this error

    2009-12-29 18:07:52.687 TestWS[6018:207] *** -[NSCFDictionary objectAtIndex:]: unrecognized selector sent to instance 0×3c03bb0
    2009-12-29 18:07:52.688 TestWS[6018:207] *** Terminating app due to uncaught exception ‘NSInvalidArgumentException’, reason: ‘*** -[NSCFDictionary objectAtIndex:]: unrecognized selector sent to instance 0×3c03bb0′

    i can get the count of rows in mydata but not the value for the cell

    what can i do???

    • o0joecool0o
      December 30, 2009 at 3:31 pm | #29

      the raw data sent back from your service is not returned as a string in the mutable array it is returned as binary data. you need to use NSXMLParser to iterate through your data and you need to turn the data into a string first.

      NSString *theXml = [[NSString alloc]initWithBytes:[mydata mutableBytes] length:[mydata length] encoding:NSUTF8StringEncoding];
      NSLog(@”response:%@”, theXml, nil);

      that should print the xml as text to the console.

  13. coco
    December 30, 2009 at 6:05 am | #30

    Ok, I finally figured it out … so in case this helps someone else here is what you need to do:

    This will only work with a dataset coming from a webservice. So anything else you try that provides standard XML will not work out of the box. So make a .asmx page with a webmethod that returns a Dataset first. I made the mistake of trying to use some generic online XML webservices to test it.

    Set the DataCon.XMLNameSpace=@”http://tempuri.org”;

    When you run this go to your output window in Xcode and see what name your table has. Mine ended up with “RequestType” … then put that in the mydata = … @”Table1″ … I changed mine to @”RequestType” in there …

    Then it magically worked!

    … if I can only put a spinner now to let the user know that the webservice is downloading … its a tad on the slow side with large tables. What I might do instead is provide a comma delimited string and parse that … it’ll be faster than the XML service and parsing but not sure if I might need something more generic later on.

    btw Great job to the gentleman that put this together … for .net folks working in Objective C feels like driving on the wrong side of the road.

  14. coco
    December 30, 2009 at 6:11 am | #31

    I would be interested in anyone knows how to return all the columns for a specific row … ie: all the fields for a record matching a specific column or key value … thoughts?

    • o0joecool0o
      December 30, 2009 at 5:20 pm | #32

      I will eventually add this when i get some down time. You could write your own in the Dataset.m class

  15. December 30, 2009 at 6:54 am | #33

    Seems like still cant get answer to the problem with the parameters in the web service method discussed earlier on. Anybody encountered this problem and has a solution to it.

    • coco
      December 30, 2009 at 6:59 am | #34

      You have a spelling error … in the C# code the param is called strUserUD and in the iPhone code you have strUserID

    • December 30, 2009 at 8:46 am | #35

      OK, i have figured out why,.. the problem with the parameters not being fed… If i inspect my asmx request and response, in the request soap message i have the following tags:

      ^GetUsers xmlns=http://tempuri.org/”^
      ^strUserID^ string ^/strUserID^
      ^/GetUsers^

      Now, after i check the request msg in the console, i spotted the difference

      ^GetUsers xmlns=http://tempuri.org”^
      ^strUserID^ string ^/strUserID^
      ^/GetUsers^

      The “/” really make a big difference! make sure you type in that XMLNameSpace correctly!

      This comes another issue, since the framework will default

      self.SOAPActionURL = [NSString stringWithFormat:@"%@/%@",self.XMLNameSpace, self.MethodName];

      this will cause my SOAPActionURL to become http://tempuri.org//GetUsers
      which the now extra “/” will cause problem. So to solve this i changed into:

      self.SOAPActionURL = [NSString stringWithFormat:@"%@%@",self.XMLNameSpace, self.MethodName];

      Also i have updated the following:

      [request addValue:SOAPActionURL forHTTPHeaderField:@"SOAPAction"];
      to
      [request addValue:self.SOAPActionURL forHTTPHeaderField:@"SOAPAction"];

      • o0joecool0o
        December 30, 2009 at 3:38 pm | #36

        hmm this is strange when I looked at my webservice.asmx the xml names space does not contain the “/” at the end like yours did. I wonder why this is.

      • Nik
        January 25, 2010 at 7:18 pm | #37

        First of all thanks o0joecool0o for sharing the code,
        John thank you as well as these modifications worked for me as well…

  16. December 30, 2009 at 8:50 am | #38

    noted the spelling error, its just my typo error here.

  17. coco
    December 30, 2009 at 5:03 pm | #39

    Does anyone know how to retrieve an entire record with all columns? For example I have a data set with name, phone, and address. When I click on a row using the tableview I would like to see the details …

    thank you in advance

    • o0joecool0o
      December 30, 2009 at 5:29 pm | #40

      for now you have to retrieve one column at a time. I will add this functionality some time later. When I have enough time I want to add SQL syntax so you can query a dataset just like a SQL table by using “SELECT * ” etc

  18. coco
    December 30, 2009 at 8:10 pm | #41

    Does anyone else have the issue where it sometimes fails to load in the simulator?

  19. January 5, 2010 at 8:37 am | #42

    when i try to load all records from my dataset, i encountered NSMallocException in :

    NSMutableDictionary *table = [[NSMutableDictionary alloc] initWithDictionary:[thisDataset.Tables objectForKey:self.currentTable]];

    this in the function (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string

    Wonder any of you experiences this?

    • o0joecool0o
      January 5, 2010 at 6:41 pm | #43

      I have never seen this error, try debugging by NSLogging the xml raw output and see if there are any special characters that could be throwing it off.

      • January 6, 2010 at 2:16 am | #44

        If Small data is ok, but i believe my dataset is Big and the above NSMutableDictionary is blown,

        i uncommented :
        NSLog(@”founddata: %@”, string);
        in
        - (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string

        and run. Initially its running very fast and smoothly and slows down as it progresses.. in debug console traces, i got the error eventually:

        NaPalmNursingAccessment(696,0xa0a4d500) malloc: *** mmap(size=2097152) failed (error code=12)
        *** error: can’t allocate region
        *** set a breakpoint in malloc_error_break to debug
        NaPalmNursingAccessment(696,0xa0a4d500) malloc: *** mmap(size=2097152) failed (error code=12)
        *** error: can’t allocate region
        *** set a breakpoint in malloc_error_break to debug
        2010-01-06 10:15:15.989 NaPalmNursingAccessment[696:207] *** Terminating app due to uncaught exception ‘NSInvalidArgumentException’, reason: ‘(null): attempt to insert nil’
        NaPalmNursingAccessment(696,0xa0a4d500) malloc: *** mmap(size=2097152) failed (error code=12)
        *** error: can’t allocate region
        *** set a breakpoint in malloc_error_break to debug

  20. Luis Enrique Ortiz
    January 6, 2010 at 12:46 am | #45

    How can i catch errors like there is no connection o servertime out???

  21. David R
    January 14, 2010 at 12:57 am | #46

    FANTASTIC work. Thanks for taking the time to post your work. It’s MUCH appreciated.

  22. TF
    January 16, 2010 at 12:00 pm | #47

    Really Fantastic piece of work. Expecting more in future from urside :)

    • o0joecool0o
      January 18, 2010 at 5:26 pm | #48

      Thanks! current project is keeping me super tied up but as soon as its complete (march) I will have time for some new posts, UIPicker POP UP (Like safari) will be my next post.

  23. Victor S
    January 18, 2010 at 10:58 pm | #49

    Hi,

    This tutorial is the best. Thank you so much for this :)

  24. January 19, 2010 at 8:59 am | #50

    Hi,

    I tried the code for my webservices, I got the following errors,

    my parameters are :

    DataCon.XMLNameSpace = @”http://www.mvirtualcity.com/thespacewebservices/TheSpaceWebServices”;
    DataCon.XMLURLAddress = @”http://www.mvirtualcity.com/thespacewebservices/TheSpaceWebServices.asmx”;
    DataCon.MethodName = @”CheckLogin”;

    The webmethod does not return any dataset, it just return an integer that indicate if the logon is successful or not.

    soap:ClientSystem.Web.Services.Protocols.SoapException: Server did not recognize the value of HTTP Header SOAPAction: http://www.mvirtualcity.com/thespacewebservices/TheSpaceWebServices/CheckLogin.
    at System.Web.Services.Protocols.Soap11ServerProtocolHelper.RouteRequest()
    at System.Web.Services.Protocols.SoapServerProtocol.RouteRequest(SoapServerMessage message)
    at System.Web.Services.Protocols.SoapServerProtocol.Initialize()
    at System.Web.Services.Protocols.ServerProtocol.SetContext(Type type, HttpContext context, HttpRequest request, HttpResponse response)
    at System.Web.Services.Protocols.ServerProtocolFactory.Create(Type type, HttpContext context, HttpRequest request, HttpResponse response, Boolean& abortProcessing)

    • o0joecool0o
      January 19, 2010 at 5:57 pm | #51

      If you are following my example above using my classes I have only written support for datasets, if you want to just accept an integer you will have to write your own XMLParser object to handle the returned data.

  25. Luis Enrique Ortiz
    January 19, 2010 at 4:06 pm | #52

    Hi

    I have one problem, in my webservice i have an sql query where i insert the parameters that i received from the iphone to a database

    in my iphone when i call the webservice, in the server its call 3 times, for example if the parameters is one i get 3 rows in my databse with the value one

    why its the iphone calling 3 times the webservice??

    can anyone help

    • o0joecool0o
      January 19, 2010 at 5:58 pm | #53

      Not sure why this would be happening Mine only ever gets called once. Double check that the method is being called 3 times and its not a SQL error thats inserting a record 3 times… If it is being called 3 tiems check your iphone code for any duplicate class instances.

    • January 26, 2010 at 11:14 pm | #54

      I am also getting this issue, when I call a method in the web service that inserts a record into the DB (once) it is inserting the same record three times. Did you figure out what was causing this?

  26. January 25, 2010 at 10:12 am | #55

    great example and thanks for the files! I have tried to get this to work but I do not seem to get a dataset back. Im using a .Net service that takes in a string parameter (RoomID) and sends back a dataset.
    Heres my code, can you see anything wrong?

    - (IBAction)btnRefreshClick:(id)sender
    {

    WebServiceHelper *DataCon = [[WebServiceHelper alloc] init];

    DataCon.XMLNameSpace = @”http://phonefling.com/FlingService”;
    DataCon.XMLURLAddress = @”http://www.phonefling.com/flingservice/flingservice.asmx”;
    DataCon.MethodName = @”GetChatLinesByRoomID”;

    DataCon.MethodParameters = [[NSMutableDictionary alloc] init];
    [DataCon.MethodParameters setObject:@"1" forKey:@"RoomID"];

    self.data = [DataCon initiateConnection];

    DataSet *dsMyDataSet = [[DataSet alloc] initWithXMLData:self.data];

    NSMutableDictionary *mydata = [[NSMutableDictionary alloc] init];
    mydata = [dsMyDataSet getRowsForTableAndColumn:@"Table1" col:@"fromUser"];
    }

    • January 25, 2010 at 10:37 am | #56

      nevermind, i am getting the data back, I just need to figure out how to work with it =)

  27. January 26, 2010 at 10:23 pm | #57

    Wow, great work!
    I’m new in iPhone Developing and work with DataSets every day. It’s quiet hard to come from c# and dive into object-c ;-)
    You saved me a lot of time!
    Thank you

  28. January 27, 2010 at 12:51 am | #58

    Im having a similar problem to the post above. Im building a chat app that currently calls a webservice to get the chat lines, and also posts a single chat line to the service. When I debug and add breakpoints, the program goes through as expected and will add a single chat line until the flow reaches the end bracket of textFieldDoneEditing. As soon as I press continue the same chatline is then posted two more times. here is my code, can you see anything wrong? Thanks!!

    - (IBAction)textFieldDoneEditing:(id)sender //POSTs a new chat line to the chatroom
    {
    [sender resignFirstResponder];
    [txtAddText resignFirstResponder];
    WebServiceHelper *DataCon = [[WebServiceHelper alloc] init];

    DataCon.XMLNameSpace = @”http://phonefling.com/FlingService”;
    DataCon.XMLURLAddress = @”http://www.phonefling.com/flingservice/flingservice.asmx”;
    DataCon.MethodName = @”InsertChatLine”;

    DataCon.MethodParameters = [[NSMutableDictionary alloc] init];
    [DataCon.MethodParameters setObject:@"1" forKey:@"RoomID"];
    [DataCon.MethodParameters setObject:@"121431" forKey:@"UserID"];
    [DataCon.MethodParameters setObject:@"Scotty" forKey:@"UserName"];
    [DataCon.MethodParameters setObject:@"" forKey:@"toUser"];
    [DataCon.MethodParameters setObject:txtAddText.text forKey:@"ChatLine"];

    [DataCon initiateConnection];

    txtAddText.text = @”";

    [DataCon release];

    [self btnRefreshClick:nil];
    }

    - (IBAction)btnRefreshClick:(id)sender //refresh chatlines
    {
    WebServiceHelper *DataCon = [[WebServiceHelper alloc] init];

    DataCon.XMLNameSpace = @”http://phonefling.com/FlingService”;
    DataCon.XMLURLAddress = @”http://www.phonefling.com/flingservice/flingservice.asmx”;
    DataCon.MethodName = @”GetChatLinesByRoomID”;

    DataCon.MethodParameters = [[NSMutableDictionary alloc] init];
    [DataCon.MethodParameters setObject:@"1" forKey:@"RoomID"];

    self.data = [DataCon initiateConnection];
    DataSet *dsMyDataSet = [[DataSet alloc] initWithXMLData:self.data];
    [wvChat loadHTMLString:html baseURL:[NSURL URLWithString:@"http://www.apple.com"]];

    [DataCon release];
    }

    • January 27, 2010 at 12:59 am | #59

      another note, when i invoke the service from the server, it only inserts one record.

  29. Luke
    February 5, 2010 at 8:14 pm | #60

    This code was exactly what I needed to get my iPhone app talking to my company’s .net web service. The only issues I’m having are that this code uses a synchronous request to download the data, which causes my UI to freeze, and that it treats each element in the soap response as a distinct ‘column’ in the table – ignoring how it actually relates to other elements in the xml tree structure that I’m getting back from the server. It would help me tremendously if there was a way to parse each node of the xml into an NSDictionary, or to simply dump the data into a .plist file. Also, if anyone knows how to change this so that it works asynchronously, or can point me in the right direction, I would really appreciate it.

  30. o0joecool0o
    February 5, 2010 at 9:18 pm | #61

    I have a new version of the code that will now store the entire table in NSDictionary format which will allow you to retrieve the records row by row instead of by column. The new structure will be
    DATASET.TABLES(NSDictionary-ofTables)
    TABLE(NSDIctionary)[Key=RowID:Value=NSDictionary-ofcolumns]
    COLUMN(NSDictionary)[Key=ColumnName:Value=String-ofData]

    This will be much more flexible in that you can retrieve an entire table of rows and loop through each single row or column depending on your needs. simply by calling [myRow objectForKey@"Column1"]. This may help you out with what you are trying to accomplish.

    I will create a brand new blog post for this new version with instructions on using it which are far more simplified. My new approach actually is much better performance wise as it does not need to loop so much to create these structures. hopefully I will have the new post done by the end of this weekend.

  31. February 9, 2010 at 1:20 am | #62

    Thanks for the great example.

    One word of warning – don’t use this code as-is. As it stands, it is leakier than a sieve. Run it under the static analyser to see the warnings and correct them for yourself.

  32. February 9, 2010 at 2:54 am | #63

    Actually, further to my last comment – this is great as sample code, but you can’t really use it in a commercial product due to the GPL license being attached to this code. Bugger.

  33. Austin
    February 12, 2010 at 10:56 pm | #64

    When I look at the soap envelope I created in the console, everything looks fine. However when I get to [Parser parse] in dataset.m, I look at *theXML and it tells me I didn’t supply the expected parameter. But its clearly there in the envelope (userName):

    Printing description of sRequest:
    austins

    here is the error:
    2010-02-12 16:56:21.519 Ring[4059:207] response:soap:ServerServer was unable to process request. —> Procedure or function ’sp_SelPastAFEsByUserName’ expects parameter ‘@userName’, which was not supplied.

    • Austin
      February 12, 2010 at 10:58 pm | #65

      It looks like the site cut off my envelope, heres my attempt to re-paste it with the userName parameter in it:

      Printing description of sRequest:
      austins

      • Austin
        February 12, 2010 at 11:01 pm | #66

        Trying one more time:

        austins

      • Austin
        February 13, 2010 at 1:19 pm | #67

        Ok, it turns out it was the same problem John had up above. It sure is misleading tho to see an error about the stored proc not receiving the parameter. It leads one to believe that we’re communicating properly with the web service.

        So if anyone else gets the same error, it has nothing to do with your parameters. Its because you missed a stupid forward slash ‘/’ somewhere in your xmlNameSpace.

  34. gokhan
    February 26, 2010 at 3:56 pm | #68

    hey;

    thanx for great post. But did you find a solution for special characters ? if there is a special character in xml structure unlike XmlDatasetParser class is unable to detect and append to previous string.Is anyone found a solution for this?

    • o0joecool0o
      March 3, 2010 at 1:21 am | #69

      This will be fixed in the next version I came accross this error when tryign to recieive an “&” character The problem is for some reason XMLPArser splits the foundcharacters method and calls it 3 times for example pass in “Me&Him” calls found characters 3 tiems with “Me” “&” “Him”. Expect a much better bersion to be posted soon. Jsut crazy busy tryign to finish a project up!

  1. No trackbacks yet.