How to call a function in Microsoft Dynamics NAV to retrieve XML using AFNetworking2

1k views Asked by At

I am an experienced iOS developer but have very basic knowledge of SOAP and various HTTP protocols.

I have a client who has created a Microsoft Dynamics NAV interface that will serve me some XML for an iOS app. I am using AFNetworking2 for the networking side and using NSXMLParser to parse the XML.

The parser works fine but I am struggling to get the XML data from the clients NAV url.

I believe I have successfully authenticated against the server but I can't seem to call the function that will return XML data for me.

I currently use this code to authenticate: AFHTTPRequestOperationManager *manager= [AFHTTPRequestOperationManager manager];

NSURLCredential *credential = [NSURLCredential credentialWithUser:[AppController sharedAppController].authUserName
                                                         password:[AppController sharedAppController].authPassword
                                                      persistence:NSURLCredentialPersistenceForSession];

NSMutableURLRequest *request = [manager.requestSerializer requestWithMethod:@"POST"
                                                                  URLString: @"http://xxx.xxx.xx.x:7056/DynamicsNAV_KPI/WS/Retail%20Company/Codeunit/Kiwi_KPI" 
                                                                 parameters:nil
                                                                      error:nil];
manager.responseSerializer = [AFXMLParserResponseSerializer serializer];
    [manager.requestSerializer setValue:@"application/xml" forHTTPHeaderField:@"Accept"];
    [manager.requestSerializer setValue:@"application/xml" forHTTPHeaderField:@"Content-Type"];
AFHTTPRequestOperation *authenticationOperation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
    [authenticationOperation setCredential:credential];

    [authenticationOperation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
        NSLog(@"Authorisation Success!");
        NSLog(@"Response XML: %@", [operation responseString]);

    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        NSLog(@"Authentication Failure: %@", error);
    }];

This seems to get me in the door as the Authorisation success! message appears in the log. I am told by my client I now need to call the “GetData_KPI” with two parameters: “user” (SERVER\username) and an empty object/variable that should hold your return xml.

I created a what I believed was a SOAP Message for this:

NSString *soapMessage = [NSString stringWithFormat:@"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
                             "<soap:Envelope\n"
                             "xmlns:c=\"http://schemas.xmlsoap.org/soap/encoding/\"\n"
                             "xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"\n"
                             "xmlns:n1=\"urn:microsoftdynamicsschemas/codeunit/Kiwi_KPI\">\n"
                             "<soap:Header></soap:Header>"
                             "<soap:Body>"
                             "<n1:GetDATA_KPI id=\"o0\" c:root=\"1\">"
                             "<n1:user>SERVER\\jdoe</n1:user>"
                             "<n1:kPIxml></n1:kPIxml>"
                             "</n1:GetData_KPI>"
                             "</soap:Body>"
                             "</soap:Envelope>"];

And added these 2 lines of code:

[request setHTTPBody: [soapMessage dataUsingEncoding:NSUTF8StringEncoding]];

[request addValue:soapMessage forHTTPHeaderField:@"SOAPAction"];

But when these 2 lines are added the authentication doesn't work and I get an error like this:

Authentication Failure: Error Domain=com.alamofire.error.serialization.response Code=-1011 "Request failed: unsupported media type (415)" UserInfo=0x188635f0 {com.alamofire.serialization.response.error.response=<NSHTTPURLResponse: 0x177ba0f0> { URL: http://xxx.xxx.xx.xx:7056/DynamicsNAV_KPI/WS/Retail%20Company/Codeunit/Kiwi_KPI } { status code: 415, headers {
    "Content-Length" = 0;
    Date = "Tue, 16 Jun 2015 21:19:55 GMT";
    Server = "Microsoft-HTTPAPI/2.0";
} }, NSErrorFailingURLKey=http://xxx.xxx.xx.x:7056/DynamicsNAV_KPI/WS/Retail%20Company/Codeunit/Kiwi_KPI, NSLocalizedDescription=Request failed: unsupported media type (415), com.alamofire.serialization.response.error.data=<>}

My questions are: 1. How do I call the function GetDataKPI using AFNetworking?

  1. How should the SOAP message be constructed to pass user name a nd a blank parameter for XML?

  2. How will I access the blank parameter to get XML?

I really am at a loss with this stuff and would really appreciate any help.

1

There are 1 answers

0
Mak Sim On

Well I can only help you with one part of the question. As I can see your client used standard feature of Nav 2009 (or older) - web services.

Let's assume you have authorized successfully. Would get http 401 otherwise.

Next. Unsuported media... dunno what this is, but you can test weather your SOAP message is valid using any app that can post soap, like soapUI (see this answer). It will also help you create and send propper message by consuming wsdl of Nav web service. So you will see both request and response in xml format. If you end up getting http 500 see this answer.

  1. How do I call the function GetDataKPI using AFNetworking?

That I can not help you with.

  1. How should the SOAP message be constructed to pass user name and a blank parameter for XML?

Use sopaUI to build valid soap(xml) request. No such thing as blank parameter needed afaik. It is defined as output xml parameter in Nav but for you it will be just soap(xml) resposnse which you will get.

  1. How will I access the blank parameter to get XML?

Parse HTTP response of your AFNetworking2 whatever this thing is =) Can only gues that it will be somwhere in responseObject.

If nothing helps try posting your web services wsdl here. May be it will clear things up.