How to use XMLPorts in Web Services (2)

24 Feb

If you haven’t already read part 1 you should do so here, before continuing to read this post.

You have seen how to use an XMLPort in a Web Service without any line of code. That was amazing, wasn’t it? Now, how was this possible?

The answer is really simple: because the XMLPort parameter is a VAR parameter (e.g. ByRef). As you know a VAR parameter in C/AL means that the parameter value can be changed by the function and the changed value will be available to code that called the function. The Service Tier detects that the XMLPort parameter is ByRef and assumes that you would like to have a return value. For this reason it calls the EXPORT function of the XMLPort automatically and returns the result as an XML formatted string.

Because the return value of an XMLPort parameter is a XML formatted string, the Service Tier uses the schema of the XMLPort to define a complex type in the WSDL. In other words: the output of the XMLPort becomes a type according to the WSDL and can be used as a strong type in Visual Studio.

Let’s have a look at the XMLPort:

and how the function in NAV looks like:

Compare this with Visual Studio.

image

At the left hand side we see the Web Service ExportData (which is the name that we used to publish the Web Service).

At the upper right hand side the ExportItems function is listed. Notice the ref before the parameter. This is because of the VAR parameter in NAV. The parameter itself is of type NAVItems. In the lower area you can also see the name of the parameter: items. This is the name of the VAR parameter in NAV. Notice that the parameter name starts with lower case, while NAV uses uppercase for the same parameter! This is by design.

The type name of the parameter is NAVItems, which is the name of root element in the XMLPort.

Let’s have a closer look at NAVItems:

image

The NAVItems type has some basic methods which are inherited from the Object type. But we are interested in the property NAVItem. In the lower area the definition is displayed of this property. This tells us that the property NAVItem is of type NAVItem[]. This means that it is an array, consisting of zero or more objects of type NAVItem.

Now we are getting closer. Let’s have a look at the type NAVItem:

image

And now we see the fields that are defined in the XMLPort: No, Description, etc.

Let’s wrap this up:

  • The XMLPort parameter becomes a strong type in Visual Studio. The name of the root element is used as type name.
  • Each element that has child elements becomes a strong type in Visual Studio. The child elements are added as properties.
  • If a child element can occur more than once, then the property becomes an array.

XMLPort schema

The basis for this behavior is of course the WSDL of the Web Service. The WSDL is used by Visual Studio to generate the proxy with the containing datatypes. The WSDL on its turn is based on the definition of the XMLPort (and the Codeunit of course). There are some properties in the XMLPort that influence the WSDL and thus influence the generated datatypes. In fact you design the schema of the XMLPort using these properties.

MinOccurs and MaxOccurs properties

These two properties specify how many times a certain element can occur. It is very important to set these properties correctly.

The root element must exactly occur one time. This is a basic rule for valid XML. To achieve this, make sure that the MinOccurs and MaxOccurs properties of the root element in the XMLPort are set to Once:

image

An element of source type Table results in one element per record in the output. Because you don’t know how many records the table contains, the MinOccurs property must be set to Zero and the MaxOccurs property to Unbounded:

image

Do not try to specify the table element as the root element. This will result in multiple root elements, which is invalid XML. Also, do not forget to set the MinOccurs property of the table element to Zero. By default the MinOccurs property has value Once. But when exporting an empty table (e.g. no records in the filter) the resulting XML does not apply to the MinOccurs rule. This will result in a runtime error of your application.

Format/Evaluate property

Set the XMLPort property Format/Evaluate to XML Format/Evaluate. This will cause Visual Studio to know the type of properties, e.g. string, decimal or boolean. By default the Format/Evaluate property is set to “C/SIDE Format/Evaluate”. In that case all properties will be string.

image

 

One remark about the Direction property. The default value is Both. When the value is set to Import it is not possible to use the XMLPort as a VAR parameter. That will result in an error ‘The XMLPort ‘Export Items’ is designed for import only.’.

Does this mean that you can also use an XMLPort in a Web Service for importing data? Yes, that is possible! It works both ways.

Until now we did not write any code in NAV. In the next post we will see how to filter the data before exporting it and how to implement paging.

15 thoughts on “How to use XMLPorts in Web Services (2)

  1. Hi,

    Can you give me example of getting multiple records back from XMLport in webservies. I tried it passing xmlport as var but i m getting balnk response.

    Thanks
    Vikas

  2. Hi Vikas,

    Sorry for the delayed reply.

    Normally the XMLPort returns multiple records. Maybe you have some filters? A good idea to test is to run the XMLPort from the client and export the results to a file. If you get results there, but no results using the webservice, than something has been incorrectly configured. Unfortunately, without code it is hard to say what part is incorrect.

    Regards,
    Arend-Jan

  3. Your web page (How to use XMLPorts in Web Services (2) Microsoft Dynamics NAV Thoughts) doesn’t show up appropriately on my I phone – you may wanna try and look at that 🙂 Wylie Schwartz

  4. Pingback: How to use XMLPorts in Web Services (2) | Pardaan.com

  5. Hi, thank you very much..

    i have a question. when i use the xmlport and set an Element with Source Type “Text”
    and on the properties i leave tha maxoccur to “unbounded”
    in the .net this Element will be mapped as an array of string -> name[]..
    ok, thats fine.

    but my question is..
    HOW CAN I FILL THE ARRAY IN NAVISION ON THE SAME RECORD?

    Saying im exporting the saleline 123
    in that i define a text element barcodes unbounded
    so i can assign multiple barcodes to the same line..

    regards

    alex

    • Hi Alex,

      I have posted an answer in the mibuso thread.

      If you have any questions left, don’t hesitate to ask them.

      Kind regards,
      Arend-Jan

  6. Hi,
    Great post!!!
    I’m trying to use with import but I’m confused. I’m programming with .net and i have already created a xmldoc with System.Xml that I want to import into Navision.
    when I try to pass xmldoc through function, it says it says “you can’t convert system.xml.xmldocument to NAVItem”. Obviously. How can I transfer to NAVitem type?
    do you have any sample to import xml?

    Thanks!

  7. I found some small problems when using xmlports in webservices.

    1. If the result which You get from NAV contains no data, then the data You receive in VS has one empty dataset.
    2. there must be a difference if a xmlport is used in code or as webservice. Try to use table 200000068 “Record Link” for a xmlport with fields Link ID, Description and Record ID. When using this xmlport in code and export it to a file, then Record ID is written into the XML-file. When using the same xmlport as webservice You will receive an error, because of field record ID.

    • using the same xmlport as webservice You will receive an error, because of field record ID.
      That’s not an xmlport issue but a RTC/classic issue. RecordID’s are different between those versions. Always use a format(recordid) before comparing/handling/exporting/…

  8. Hi Arend-Jan,
    We use XMLports in webservices, always using the “var” trick, especially with responses.
    In a new project we cannot use the var trick anymore, because the response needs to a “confirmation XML “ structure, or a “application SOAP-FAULT” structure.
    We tried to produce the required answer manually by calling the XMLPORT.EXPORT function, but we cannot get it working, we only get HTTP 500, invalid xmlnode:

    SoapErrPort.SETTABLEVIEW(ErrTable);
    TempBlob.Blob.CREATEOUTSTREAM(OutStr);
    SoapErrPort.SETDESTINATION(OutStr);
    SoapErrPort.EXPORT;
    TempBlob.Blob.CREATEINSTREAM(InStr);
    BigTekstParm.READ(InStr);

    Any suggestions?

    Benno

  9. Hi and thank you for your post. I have on question, we are using Java instead of C# to consume the XMLPort web service. In Java I use JAXB to consume the WSDL and generate Java class stubs. The problem with that is that when using a Text element as root element then Dynamics Nav inserts and attribute “mixed=true” into the WSDL definition of the root element. Like this:

    It seems in C# this is no problem but in Java it causes the content of the root element to be of the generic type Serializable:

    See also this question on stack overflow, which demonstrates a similar problem:
    http://stackoverflow.com/questions/12568247/how-to-deal-with-jaxb-complextype-with-mixedcontent-data

    In particular I have to write
    rootElementType.getContent().add(Serializable element);

    Because of this I need to to write the following code:

    RootElement rootElement = new Root();
    SomeType sometype = …;
    rootElement.getContent().add(new JAXBElement(new QName(“urn:microsoft-dynamics-nav/xmlports/x50000”, “SomeType”), SomeType.class, sometype));

    It is quite ugly and it forces me to handle the namespace in the code, which I would like to avoid. So I am wondering if there is any alternative to using a Text element as root element or if nav can be configured in some way to avoid the mixed definition in the WSDL?

Leave a Reply

Your email address will not be published.