mibuso.com

Microsoft Business Solutions online community
It is currently Thu Apr 24, 2014 10:56 am

All times are UTC + 1 hour [ DST ]




Post new topic Reply to topic  [ 15 posts ] 
Author Message
 Post subject: How to consume a webservice with XMLports and HTTP POST
PostPosted: Thu Jan 31, 2008 5:57 pm 
Offline

Joined: Fri Jun 02, 2000 7:01 am
Posts: 44
Location: Manchester, UK
Country: United Kingdom (uk)
I know the subject of consuming web services has been covered elsewhere in posts and documents. However, all of them seem to either use a simple string for the XML message or build it element by element. The problem is that the former is no good for large messages and the latter is a bit unwieldy, especially when we have XMLports available.

So here is a post showing how to use XMLports to handle the XML messages when you want to consume a webservice. The scenario is that we want to send a request for data to a webservice and get back one or more records. We will use HTTP POST to communicate with the webservice.

Start with the format of the request message:

(By the way, the website and webservice do NOT exist so do NOT bother trying to use them)

Code: Select all
POST /DataService.asmx HTTP/1.1
Host: fat-aardvark.net
Content-Type: text/xml; charset=utf-8
SOAPAction: "http://tempuri.org/SelectData"

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <soap:Body>
    <SelectData xmlns="http://tempuri.org/" />
  </soap:Body>
</soap:Envelope>


To which the webservice responds with this:

Code: Select all
HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: length

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <SelectDataResponse xmlns="http://tempuri.org/">
      <SelectDataResult>
        <Data>
          <ID>int</ID>
          <Code>int</Code>
          <Type>int</Type>
          <Name>string</Name>
        </Data>
        <Data>
          <ID>int</ID>
          <Code>int</Code>
          <Type>int</Type>
          <Name>string</Name>
        </Data>
      </SelectDataResult>
    </SelectDataResponse>
  </soap:Body>
</soap:Envelope>


Note that the data element will be repeated once per record that is being returned.

We'll start by building an XMLport to create the request message.

Code: Select all
TagName           TagType    SourceType  DataSource

soap:Envelope     Element    Text        <soap:Envelope>
  xmlns:soap      Attribute  Text        NS1
  xmlns:xsi       Attribute  Text        NS2
  xmlns:xsd       Attribute  Text        NS3
    soap:Body     Element    Text        <soap:Body>
      SelectData  Element    Text        <SelectData>
        xmlns     Attribute  Text        NS4


Add the following text constants to hold all the namespaces in the request

Code: Select all
Name    ConstValue
NSpace1 http://schemas.xmlsoap.org/soap/envelope/
NSpace2 http://www.w3.org/2001/XMLSchema-instance
NSpace3 http://www.w3.org/2001/XMLSchema
NSpace4 http://tempuri.org/


And put them in the right values when we run the XMLport with this bit of code

Code: Select all
OnPreXMLport()
NS1 := NSpace1;
NS2 := NSpace2;
NS3 := NSpace3;
NS4 := NSpace4;


Obviously, if you need to send some other data then you put the relevant code/elements/attributes into this XMLport.

Now we need an XMLport to handle the response. I know later XMLports allow you to read in XML namespace information but this example will strip that out of the response so that we don't have to worry about it. This will allow you to use this example in earlier systems too.

Code: Select all
TagName                 TagType  SourceType  DataSource

Envelope                Element  Text        <Envelope>
  Body                  Element  Text        <Body>
    SelectDataResponse  Element  Text        <SelectDataResponse>
      SelectDataResult  Element  Text        <SelectDataResult>
        Data            Element  Text        <Data>
          ID            Element  Text        D1
          Code          Element  Text        D2
          Type          Element  Text        D3
          Name          Element  Text        D4


When this runs, it will read each record into the D1, D2, D3 & D4 global variables and you will then need to add code to the XMLport to do something with that data (remember that they will be text values). Alternatively, you could specify a table and replace the D1/2/3/4 with field names in that table. It's up to you what you do with the XMLport once it has the data.

Now for a codeunit to bring them together and do the dirty work.

Setup some global variables:

Code: Select all
Name         DataType    Subtype
XP1          XMLport     <name of the first XMLport>
XP2          XMLport     <name of the second XMLport>
XMLDoc       Automation  'Microsoft XML, v5.0'.DOMDocument
XMLHttpConn  Automation  'Microsoft XML, v5.0'.ServerXMLHTTP
InStr        InStream
OutStr       OutStream


Add a function called SendMessage and setup a local variable:

Code: Select all
Name         DataType    Subtype
TempTable    Record      TempBlob (set this as a temporary table!)


Add another function called RemoveNamespace which has the parameters:

Code: Select all
Var  Name         DataType    Subtype
No   Source       Automation  'Microsoft XML, v5.0'.DOMDocument
Yes  Destination  Automation  'Microsoft XML, v5.0'.DOMDocument


and the local variables:

Code: Select all
Name           DataType    Subtype
TempTable      Record      TempBlob (set this as a temporary table!)
XMLStyleSheet  Automation  'Microsoft XML, v5.0'.DOMDocument
StyleOutStr    OutStream      
StyleInStr     InStream      


Now add the code as follows:

Code: Select all
======================================================
OnRun()
======================================================

SendMessage;

======================================================
SendMessage()
======================================================

//setup the temporary table so that we can handle the XML without saving it to disk first
//create a couple of streams to transfer the data in and out of the BLOB field
CLEAR(TempTable);
TempTable.Blob.CREATEINSTREAM(InStr);
TempTable.Blob.CREATEOUTSTREAM(OutStr);

//the request XMLport fills the BLOB with the XML message
CLEAR(XP1);
XP1.SETDESTINATION(OutStr);
XP1.EXPORT;

//load the message into the XML automation variable
IF ISCLEAR(XMLDoc) THEN
  CREATE(XMLDoc);
XMLDoc.load(InStr);

//this is for diagnostics only, so you can see what the XMLport actually produced
XMLDoc.save('C:\Temp\XMLRequest.txt');

//create the HTTP connector
IF ISCLEAR(XMLHttpConn) THEN
  CREATE(XMLHttpConn);

//tell it where the web service is located
XMLHttpConn.open('POST','http://fat-aardvark.net/DataService.asmx',FALSE);

//set some values in the request header depending on what the service requires
XMLHttpConn.setRequestHeader('Host','fat-aardvark.net');
XMLHttpConn.setRequestHeader('SOAPAction','http://tempuri.org/SelectData');
XMLHttpConn.setRequestHeader('Content-Type','text/xml');

//actually send the message
XMLHttpConn.send(XMLDoc);

//get the response
XMLDoc.load(XMLHttpConn.responseXML);

//tell us if we got an error (it is 200 because the response definition said "200 OK")
IF XMLHttpConn.status <> 200 THEN BEGIN
  MESSAGE('Status %1 %2',XMLHttpConn.status,XMLHttpConn.statusText);
  EXIT;
END;

//this is for diagnostics only, so you can see what you got back
XMLDoc.save('C:\Temp\XMLResponse1.xml');

//take away the namespaces
RemoveNamespace(XMLDoc,XMLDoc);

//this is for diagnostics only, so you can see what it looks like after the namespaces have gone
XMLDoc.save('C:\Temp\XMLResponse2.xml');

//fill the BLOB with the response XML
XMLDoc.save(OutStr);

//the response XMLport reads the data from the BLOB and processes it
CLEAR(XP2);
XP2.SETSOURCE(InStr);
XP2.IMPORT;

======================================================
RemoveNamespace
======================================================

//this has been taken from a Microsoft knowledgebase aricle and strips out the
//namespaces from an XML message using a style sheet

TempTable.Blob.CREATEOUTSTREAM(StyleOutStr);
TempTable.Blob.CREATEINSTREAM(StyleInStr);
StyleOutStr.WRITETEXT('<?xml version="1.0" encoding="UTF-8"?>');
StyleOutStr.WRITETEXT('<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">');
StyleOutStr.WRITETEXT('<xsl:output method="xml" encoding="UTF-8" />');
StyleOutStr.WRITETEXT('<xsl:template match="/">');
StyleOutStr.WRITETEXT('<xsl:copy>');
StyleOutStr.WRITETEXT('<xsl:apply-templates />');
StyleOutStr.WRITETEXT('</xsl:copy>');
StyleOutStr.WRITETEXT('</xsl:template>');
StyleOutStr.WRITETEXT('<xsl:template match="*">');
StyleOutStr.WRITETEXT('<xsl:element name="{local-name()}">');
StyleOutStr.WRITETEXT('<xsl:apply-templates select="@* | node()" />');
StyleOutStr.WRITETEXT('</xsl:element>');
StyleOutStr.WRITETEXT('</xsl:template>');
StyleOutStr.WRITETEXT('<xsl:template match="@*">');
StyleOutStr.WRITETEXT('<xsl:attribute name="{local-name()}"><xsl:value-of select="."/></xsl:attribute>');
StyleOutStr.WRITETEXT('</xsl:template>');
StyleOutStr.WRITETEXT('<xsl:template match="text() | processing-instruction() | comment()">');
StyleOutStr.WRITETEXT('<xsl:copy />');
StyleOutStr.WRITETEXT('</xsl:template>');
StyleOutStr.WRITETEXT('</xsl:stylesheet>');
IF ISCLEAR(XMLStyleSheet) THEN
  CREATE(XMLStyleSheet);
XMLStyleSheet.load(StyleInStr);
IF ISCLEAR(Destination) THEN
  CREATE(Destination);
Source.transformNodeToObject(XMLStyleSheet,Destination);


There you go. Hope it helps someone out there.
No warranty express or implied.
Cheers
John


Top
 Profile E-mail  
 
 Post subject:
PostPosted: Fri Feb 01, 2008 4:36 pm 
Offline

Joined: Thu Jul 17, 2003 10:52 pm
Posts: 639
Location: Capelle a/d IJssel
Country: Netherlands (nl)
Thx, looks very detailed but i'm little bit lost in which situation I can use this. Can I use this in a NAS to NAS situation? Does this use the MSMQ?
A link for more info would be appreciated..

_________________
Create dynamic Excel or Word documents, ReportX


Top
 Profile  
 
 Post subject:
PostPosted: Fri Feb 01, 2008 5:27 pm 
Offline

Joined: Fri Jun 02, 2000 7:01 am
Posts: 44
Location: Manchester, UK
Country: United Kingdom (uk)
Simple answer first. No, this does not use MSMQ. This is for direct communication with a third party webservice. Whether you initiate this communication from an object running in NAS or from elsewhere in Navision is up to you.

Example 1: You are doing a telesales system and you want to validate a credit card and get an authorisation while the customer is on the phone. You find a credit card service provider and they give you details of their webservice. You send a request with the credit card details and they send you an authorisation number if the card is OK or an error if it is not. For this, you would have a form in NAV where you enter the details and then the user clicks a button to call this code. It takes the details they have entered and uses the first XMLport to format the request. The response XMLport then updates the payment details with the authorisation it receives.

Example 2: It is not uncommon for companies to want to trade through a website but they don't want the hassle of administering it themselves so they buy the service from a provider. The provider hosts & maintains the website and holds the data in their own database. You now need to get the orders from that database and keep the website updated with prices and stock levels. The provider gives you details of a webservice that you can use to read/write your data. You would then create a codeunit to run in NAS uses this code to periodically send a request for orders to the website which then responds with a list of orders that you import through the XMLport. Conversely, you format a request that tells the website how much stock you have of an item and the website responds with an acknowledgement.

This is all about consuming somebody else's webservice, not communicating with another NAV database (there maybe a NAV database behind the webservice but that isn't something that you need to know when you are consuming the service).

Cheers
John


Top
 Profile E-mail  
 
 Post subject:
PostPosted: Fri Feb 01, 2008 10:48 pm 
Offline

Joined: Thu Jul 17, 2003 10:52 pm
Posts: 639
Location: Capelle a/d IJssel
Country: Netherlands (nl)
I'm a bit new on xmlports...Is this like a waiting http service? or just a way to send an xml file to a website which answers with a new xml file?

_________________
Create dynamic Excel or Word documents, ReportX


Top
 Profile  
 
 Post subject:
PostPosted: Mon Feb 04, 2008 12:00 pm 
Offline

Joined: Fri Jun 02, 2000 7:01 am
Posts: 44
Location: Manchester, UK
Country: United Kingdom (uk)
An XMLport is like a dataport except that it uses XML files instead of text files. In other words it serializes & de-serializes XML.

Correct. It is a way of sending an XML file to a webservice and getting an XML file in return. That exchange may be you requesting something from the webservice or you telling the webservice to do something and it responds telling you that it has done it.

Cheers
John


Top
 Profile E-mail  
 
 Post subject:
PostPosted: Mon Feb 04, 2008 12:58 pm 
Offline

Joined: Thu Jul 17, 2003 10:52 pm
Posts: 639
Location: Capelle a/d IJssel
Country: Netherlands (nl)
Can the NAS wait on a port for requests? or is this done by the msmq from iis? (lot of questions, sorry)

_________________
Create dynamic Excel or Word documents, ReportX


Top
 Profile  
 
 Post subject:
PostPosted: Mon Feb 04, 2008 2:01 pm 
Offline

Joined: Mon Mar 08, 2004 2:42 pm
Posts: 3255
Location: Hannover
Country: Germany (de)
the nas can wait on an port. tak a look into CU 7700 (ADCS NAS Startup)

_________________
Do you make it right, it works too!


Top
 Profile  
 
 Post subject:
PostPosted: Mon Mar 17, 2008 6:30 pm 
Offline

Joined: Tue Mar 14, 2006 10:23 am
Posts: 23
Location: Norway
Country: Norway (no)
Hello John,

Thanks for your detailed description on the xml port webservice caller.

Can you give us an example on how to make Navision work the other way around - as a webservice receiving request as xml documents from sockets and sending back answers ?

I did look into CU 7700, but can you please show me how to incorporate the NAS as a webservice with your example so that Navision is listening for the xml's and then replies with a new xml file to the request ?


Top
 Profile  
 
 Post subject: Re: How to consume a webservice with XMLports and HTTP POST
PostPosted: Mon Apr 06, 2009 11:09 am 
Offline

Joined: Fri Nov 14, 2008 5:06 pm
Posts: 119
Hello

I'm trying to use this with NAV 3.70. I ran into trouble when I got to:

Name DataType Subtype
TempTable Record TempBlob (set this as a temporary table!)

I can not find the subtype "TempBlob". Should I create this table? If so what filed(s) and properties should I give it?


Top
 Profile E-mail  
 
 Post subject: Re: How to consume a webservice with XMLports and HTTP POST
PostPosted: Mon Apr 06, 2009 11:17 am 
Offline
MVP Microsoft Dynamics NAV

Joined: Thu Oct 16, 2003 8:50 am
Posts: 12283
Location: Brno
Country: Czech Republic (cz)
Yes, you can. It is only table with two fields - primary key (integer) and blob field.

_________________
Kamil Sacek
MVP - Dynamics NAV
My BLOG
NAVERTICA a.s.


Top
 Profile E-mail WWW  
 
 Post subject: Re: How to consume a webservice with XMLports and HTTP POST
PostPosted: Wed Feb 17, 2010 4:50 pm 
Offline

Joined: Tue Dec 02, 2008 11:27 am
Posts: 10
Thanks for much for this... really interesting, got it working today. Great post.


Top
 Profile E-mail  
 
 Post subject: Re: How to consume a webservice with XMLports and HTTP POST
PostPosted: Wed Sep 22, 2010 3:43 am 
Offline

Joined: Thu Feb 21, 2008 12:56 pm
Posts: 8
Location: Delhi
Country: India (in)
Hi, could someone please help, as i am getting the below shown error

" This message is for C/AL programmers:

The call to member save failed. msxml3.dll returned the following message:
The system cannot find the path specified."

I have registered the msxml3.dll(SP7) using regsvr32, I have tried using the automation variable 'Microsoft XML, v6.0'.ServerXMLHTTP'
'Microsoft XML, v4.0'.ServerXMLHTTP' but could not found 'Microsoft XML, v5.0'.ServerXMLHTTP', considering the v4.0 , v5.0 as the version of xml, i tried looking for msxml5.0.dll as well but it says that it specifically meant for office products, which i don't have installed currently on my system.

So, My question is, "Is it important to use only 'Microsoft XML, v5.0'.ServerXMLHTTP" if yes do i need to have msxml5.dll
if not important then it means i can use other versions, then why i am getting the error of msxml3.dll

Your help will be highly appreciated.

Thanks
Chander


Top
 Profile  
 
 Post subject: Re: How to consume a webservice with XMLports and HTTP POST
PostPosted: Tue Jan 04, 2011 11:45 am 
Offline

Joined: Thu Jan 15, 2009 7:12 am
Posts: 161
Country: India (in)
Hi Guys,

I am also facing the same error popping.

" This message is for C/AL programmers:

The call to member save failed. msxml3.dll returned the following message:
The system cannot find the path specified."


Can anyone tell what and why it is?

Thanks,
Aravindh


Top
 Profile E-mail  
 
 Post subject: Re: How to consume a webservice with XMLports and HTTP POST
PostPosted: Mon Sep 05, 2011 12:09 pm 
Offline

Joined: Wed Apr 04, 2007 3:34 pm
Posts: 374
Location: Finland
Country: Finland (fi)
I'm also getting this error, has anyone found a solution for this?


Attachments:
error.png
error.png [ 12.82 KiB | Viewed 9046 times ]

_________________
K.S.
Top
 Profile E-mail  
 
 Post subject: Re: How to consume a webservice with XMLports and HTTP POST
PostPosted: Tue Jan 03, 2012 5:17 pm 
Offline

Joined: Tue Jan 03, 2012 5:12 pm
Posts: 1
Country: Bangladesh (bd)
That's the xml dom document 3.0 msxml3.dll article you all are looking for..


Top
 Profile E-mail  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 15 posts ] 

All times are UTC + 1 hour [ DST ]


Who is online

Users browsing this forum: No registered users and 2 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum


Search for:
Jump to: