SUDZC webservices always return 0 (WCF web service and IOS client)

by Mark Deraeve 7. August 2012 04:10

This occurs when you are using ARC (Automatic Reference Counting) generated code.

I found the place to look on these websites: http://stackoverflow.com/questions/8645637/sudzc-with-ios-5-and-arc 

and http://code.google.com/p/sudzc/issues/detail?id=40 but it didn't solve my problem completely. 

In my case it was an .Net web service (WCF) and I had to use s:Body in stead of Body in the SUDZC generated file: SoapRequest.m

CXMLNode* element = [[SoapgetNode: [doc rootElement] withName: @"s:Body"] childAtIndex:0]; 

Found it out by NSLogging the CXML document (I used NSLog tp inspect the cxmldocument ):

        CXMLNode* test = [doc rootElement];

        

        NSLog(@"%@",test); 

Here I got this:

<CXMLElement 0x68c1a50 [0x68c1b10] s:Envelope  <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"> <s:Body><GetUserIDResponse xmlns="http://tempuri.org/"><GetUserIDResult>8</GetUserIDResult></GetUserIDResponse></s:Body> </s:Envelope> >

 

So if in your case the s:Body still doesn't do the trick, look into the XML code and find out which prefix to use! Soon I will be posting a complete solution using WCF web serivces and SUDZC generator for iOS 5. It will be a local service running on the local network, not available through the internet. 

Now an extra finding when you are working with custom objects. In my case I'm using Entity Framework with self tracking entities. There entities are passed over the WCF webservice. SUDZC will generate these objects for you and adds them to a NSMutableArray. But when you look at the objects in the array you will notice all properties are empty or nil. Therefore I had to make another change in the generated objects. In the exemple below I changed the generated code withName: @ChangeTracker ... into withName: @"a:ChangeTracker ... I had to change this for all the properties of the entity. So they were filled with the data coming from the xml!

NSMutableString* s = [superserializeElements];

[s appendFormat: @"<a:CashPayment>%@</a:CashPayment>", (self.CashPayment)?@"true":@"false"];

if (self.ChangeTracker != nil) [s appendString: [self.ChangeTrackerserialize: @"a:ChangeTracker"]];

if (self.City != nil) [s appendFormat: @"<a:City>%@</a:City>", [[self.CitystringByReplacingOccurrencesOfString:@"\""withString:@"&quot;" 

 

Be advised that when you start inserting or updating data, you will also need to change some generated code. You will need to add the namespace to the serialization code in the Soap.h and Soap.m file. The I created an extra method which will add the namespace to the envelope: 

// Creates the XML request for the SOAP envelope with optional SOAP headers and an extra given namespace.

+ (NSString*) createEnvelope: (NSString*) method forNamespace: (NSString*) ns withParameters: (NSArray*) params withHeaders: (NSDictionary*) headers  withExtraNameSpace: (NSString *) extraNameSpace;

 

Then in the Soap.m file we implement this method like this:


 

NSString* const SOAP_PREFIX = @"soapenv";

NSString* const NS_PREFIX = @"tem";

NSString* const SER_PREFIX_URL = @"xmlns:ser=\"http://schemas.microsoft.com/2003/10/Serialization/\"";

 

NSString* const HTTP_PREFIX = @"http://";

NSUInteger const FORWARD_FLASH_CHARACTER_VALUE = 47;

// Creates the XML request for the SOAP envelope with optional SOAP headers.

+ (NSString*) createEnvelope: (NSString*) method forNamespace: (NSString*) ns

forParameters: (NSString*) params withHeaders: (NSDictionary*) headers withExtraNameSpace: (NSString *) extraNameSpace

{

    

    NSMutableString* s = [NSMutableStringstring];

    /* example header <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tem="http://tempuri.org/" xmlns:ser="http://schemas.microsoft.com/2003/10/Serialization/" xmlns:gal="http://schemas.datacontract.org/2004/07/MyNamespace">*/

    [s appendString: @"<?xml version=\"1.0\" encoding=\"utf-8\"?>"];

 

    [s appendString: @"<"];

    [s appendString: SOAP_PREFIX];

    [s appendString:@":Envelope xmlns:"];

    [s appendString: SOAP_PREFIX];

    [s appendString: @"=\"http://schemas.xmlsoap.org/soap/envelope/\" "];

    [s appendString:@" xmlns:"];

    [s appendString: NS_PREFIX];

    [s appendFormat:@"=\"%@\" ",ns ];

    [s appendFormat:@"%@ ",SER_PREFIX_URL];

    if(extraNameSpace)

    {

        [s appendFormat:@" %@ >",extraNameSpace];

    }

    

    if(headers != nil && headers.count > 0) {

        [s appendString: @"<"];

        [s appendString: SOAP_PREFIX];

        [s appendString:@":Header>"];

        

        for(id key in [headers allKeys]) {

            if([[headers objectForKey: key] isMemberOfClass: [SoapNil class]])

            {

                [s appendFormat: @"<%@ xsi:nil=\"true\"/>", key];

            } else {

                [s appendString:[Soap serializeHeader:headers forKey:key]];

            }

        }

        [s appendString: @"</"];

        [s appendString: SOAP_PREFIX];

        [s appendString:@":Header>"];

    }

    

    [s appendString: @"<"];

    [s appendString: SOAP_PREFIX];

    [s appendString:@":Body>"];

    

    NSMutableString* fullMethodName = [NSMutableStringstring];

    [fullMethodName appendString:NS_PREFIX];

    [fullMethodName appendString:@":"];

    [fullMethodName appendString:method];

    

    [s appendFormat: @"<%@>%@</%@>", fullMethodName,[params

                                                     stringByReplacingOccurrencesOfString:@"&" withString:@"&amp;"],

     fullMethodName];

    

    

    [s appendString: @"</"];

    [s appendString: SOAP_PREFIX];

    [s appendString:@":Body>"];

    [s appendString: @"</"];

    [s appendString: SOAP_PREFIX];

    [s appendString:@":Envelope>"];

    return s;

}

 

So in this implementation you see there are more namespaces given. This I discovered after inspecting the WSDL xml and looking for the envelope structure. It could be that in your case the namespace prefix are different. Inspect this yourself.

Then when you call the insert function, just add the extra namespace to the create envelope:

NSString* _envelope = [SoapcreateEnvelope: @"InsertSomething"forNamespace: self.namespacewithParameters: _params withHeaders: self.headers  withExtraNameSpace:SOAP_FUNCTION_PREFIX];


The constant SOAP_FUNCTION_PREFIX looks like this: 

NSString* const SOAP_FUNCTION_PREFIX = @"xmlns:a=\"http://schemas.datacontract.org/2004/07/MyNamespace\""; 


Tags: ,

Pingbacks and trackbacks (1)+

Add comment

  Country flag

biuquote
  • Comment
  • Preview
Loading

About the author

I started as a VB6 developer, programming all kinds of applications. I also got involved in the development of a e-market in ASP.

When .Net was introduced, I had the privilege to start in a team of professionals and develop a framework. I learned a lot and started to work as a c#.Net consultant from then on.

After 2 years I also got the chance to work for several months with Sharepoint. Sharepoint kept chasing me all the years after and when the product got more and more mature I started to love it. Now Sharepoint is a somewhat daily occupation for me. I implemented a large quality document management system at PMRL being the only developper/technical analyst. Working close togehter with the QA department we succeeded in making and improving a very good Quality document management system. Its used up until this day.

I worked for 6 years as a .Net consultant for 2 of the largest consultancy companies in Belgium. I mainly worked as a Sharepoint engineer, but also .Net expert and several ASP.Net and Windows applications. One of my last projects with the consultancy was creating a custom LIMS system. This was a succes and the customer asked me to stay and help to expand and maintain this LIMS. I had great years in this company. There was a focus on innovation and a lot of opportunities for improving and developping new IS systems. Apart from several small projects I further more improved the custom LIMS system, created a SOP library based on Sharepoint and a web based Skill matrix system to handle the skills of the employees in the company. 

Then I was involved in transferring the LIMS to a new lab in Singapore. This was done in a short time frame. The deployment was again a success and it passed the GLP inspection tests. I learned a lot from the Quality engineers about validation of computerized systems.

At my current job I have a wide range of challenges. Mainly I'm still working with .Net (VB.net and C#.Net). But outside of the Microsoft world I also do some ABAB programming in our SAP system. Like developing Adobe Forms and the program behind it. Or making small changes to customized code.

Latest I started to follow a course from Stanford Univercity on Objective C programming for IPAD and IPHONE.I just finished the first app for IPad and it appears to be a great succes. People in the factory are working with IPad to take pictures and upload them to orders. Already more and more projects are coming my way. The iOS apps are supported by a home made .Net architecture that exposes WCF services. Its working great. My second app is almost ready for deployment in factories. Now I started an App for the management team so they can manage projects on their IPAD and IPHONE.

My linkedIn!

Month List

Tag cloud

Youtube

Locations of visitors to this page