web
You’re offline. This is a read only version of the page.
close
Skip to main content
Community site session details

Community site session details

Session Id :
Small and medium business | Business Central, N...
Suggested answer

SOAP Request and passing the XML values to codeunit

(5) ShareShare
ReportReport
Posted on by 25
Hello!
I need your help with parsing or interpreting the XML SOAP request in my Business Central Cloud. 

This is the Codeunit I have so far:
 
codeunit 50104 "AmirCustomer"
{
    [ServiceEnabled]
    procedure saveCustVend(_custVendDC: Text): Text
    var
        RootNode: XmlNode;
        AccountNum: Text[20];
        Name: Text[100];
    begin
        // Load XML from text
        if not LoadXMLNodeFromText(_custVendDC, RootNode) then
            Error('Failed to load XML document.');
        // Find the AccountNum node with namespace
        AccountNum := FindNodeTextWithNameSpace(RootNode, 'd4p1:AccountNum', 'd4p1', 'http://schemas.datacontract.org/2004/07/Dynamics.AX.Application');
        if AccountNum = '' then
            Error('AccountNum node not found.');
        // Find the Name node with namespace
        Name := FindNodeTextWithNameSpace(RootNode, 'd4p1:Name', 'd4p1', 'http://schemas.datacontract.org/2004/07/Dynamics.AX.Application');
        if Name = '' then
            Error('Name node not found.');
        // You now have both AccountNum and Name extracted from the XML
        exit('AccountNum: ' + AccountNum + ', Name: ' + Name);
    end;
    // Helper function to load XML from text
    procedure LoadXMLNodeFromText(pXMLText: Text; var pXMLRootNode: XmlNode): Boolean
    var
        lXmlDocument: XmlDocument;
    begin
        LoadXMLDocumentFromText(pXMLText, lXmlDocument);
        pXMLRootNode := lXmlDocument.AsXmlNode;
        exit(not pXMLRootNode.AsXmlElement().IsEmpty);
    end;
    // Helper function to load XML document from text
    procedure LoadXMLDocumentFromText(pXMLText: Text; var pXMLDocument: XmlDocument)
    begin
        if pXMLText = '' then
            exit;
        XmlDocument.ReadFrom(pXMLText, pXMLDocument);
    end;
    // Procedure for finding node text with namespaces
    procedure FindNodeTextWithNameSpace(pXMLRootNode: XmlNode; pNodePath: Text; pPrefix: Text; pNamespace: Text): Text
    var
        lXmlNode: XmlNode;
        lXmlNsMgr: XmlNamespaceManager;
    begin
        if pXMLRootNode.AsXmlElement.IsEmpty then
            exit('');
        lXmlNsMgr.NameTable(pXMLRootNode.AsXmlDocument.NameTable);
        lXmlNsMgr.AddNamespace(pPrefix, pNamespace);
        if pXMLRootNode.SelectSingleNode(pNodePath, lXmlNsMgr, lXmlNode) then
            exit(lXmlNode.AsXmlElement.InnerText);
        exit('');
    end;
}



With this codeunit I get this response:
 
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
    <s:Body>
        <s:Fault>
            <faultcode xmlns:a="urn:microsoft-dynamics-schemas/error">a:Microsoft.Dynamics.Nav.Types.Exceptions.NavNCLXmlException</faultcode>
            <faultstring xml:lang="en-US">The following exception was encountered when processing XML data: 'Data at the root level is invalid. Line 2, position 3.' at line 2 and position 3.</faultstring>
            <detail>
                <string xmlns="http://schemas.microsoft.com/2003/10/Serialization/">The following exception was encountered when processing XML data: 'Data at the root level is invalid. Line 2, position 3.' at line 2 and position 3.</string>
            </detail>
        </s:Fault>
    </s:Body>
</s:Envelope>
 
 
 
This is my SOAP request:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
    <Action s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://tempuri.org/AmirCustomer/saveCustVend</Action>
    <h:CallContext xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns:h="http://schemas.microsoft.com/dynamics/2013/01/datacontracts">
      <h:Company i:nil="true" />
      <h:Language i:nil="true" />
      <h:MessageId i:nil="true" />
      <h:PartitionKey i:nil="true" />
    </h:CallContext>
  </s:Header>
  <s:Body>
    <saveCustVend xmlns="urn:microsoft-dynamics-schemas/codeunit/AmirCustomer">
      <_custVendDC xmlns:d4p1="http://schemas.datacontract.org/2004/07/Dynamics.AX.Application" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
        <d4p1:AccountNum>32659</d4p1:AccountNum>
        <d4p1:Active>No</d4p1:Active>
        <d4p1:BusinessUnit i:nil="true" />      
        <d4p1:CostCenter i:nil="true" />
        <d4p1:Currency>USD</d4p1:Currency>
        <d4p1:CustClassificationId i:nil="true" />
        <d4p1:CustGroup>YD_KURUM</d4p1:CustGroup>
        <d4p1:Donem i:nil="true" />
        <d4p1:ElectronicAddress />
        <d4p1:HospitalCode>MED</d4p1:HospitalCode>
        <d4p1:IsCustomer>Yes</d4p1:IsCustomer>
        <d4p1:IsVendor>No</d4p1:IsVendor>
        <d4p1:Name>ACME</d4p1:Name>
        <d4p1:PaymMode>Null</d4p1:PaymMode>
        <d4p1:PaymTerm>G030</d4p1:PaymTerm>
        <d4p1:PdsCustRebateGroupId i:nil="true" />
        <d4p1:PostalAddress>
          <d4p1:PostalAddress>
            <d4p1:Country>USA</d4p1:Country>
            <d4p1:County i:nil="true" />
            <d4p1:RoleType>Invoice</d4p1:RoleType>
            <d4p1:State />
            <d4p1:Street>A Delaware, USA Company,Offices Located at 7600 Corporate Center Dr #500, Miami, FL 33126 USA,</d4p1:Street>
          </d4p1:PostalAddress>
        </d4p1:PostalAddress>  
        <d4p1:TaxGroup>YI_FTR</d4p1:TaxGroup>
        <d4p1:TaxOfficeName i:nil="true" />
       <d4p1:VATNum i:nil="true" />
       <d4p1:ValueStream i:nil="true" />
<d4p1:VendGroup>Null</d4p1:VendGroup>
      </_custVendDC>
    </saveCustVend>
  </s:Body>
</s:Envelope>
 
 
For now I would just like to get AccountNum and Name xml tag values  and display them in response... later I will add code to create a new customer with all these information... The main problem for me now is the ability to pass the request data into the codeunit...
 
Thank you so much in advance
Amir.
 
I have the same question (0)
  • Suresh Kulla Profile Picture
    49,952 Super User 2025 Season 2 on at
    SOAP Request and passing the XML values to codeunit
    @Rishabh Kanaskar, I am not sure why you are responding to a post that was made over a year ago. 
  • Suggested answer
    Jeffrey Bulanadi Profile Picture
    8,311 on at
    SOAP Request and passing the XML values to codeunit

    Hi Amir,

    The error you're seeing (“Data at the root level is invalid”) typically means the XML string passed into your codeunit contains extra whitespace, line breaks, or encoding issues that prevent it from being parsed cleanly.

    Here’s how to fix this and get your AccountNum and Name values working:

    First, confirm that the _custVendDC parameter passed into your saveCustVend procedure is only the inner XML payload, not the full SOAP envelope. BC expects a clean XML fragment, if you pass the entire SOAP envelope, it will fail at root level.

    To isolate the payload:

    • If you’re calling the codeunit via SOAP, make sure the _custVendDC parameter contains only the <_custVendDC>...</_custVendDC> block.
    • If you’re testing manually, strip out the <s:Envelope> and <s:Body> wrappers before passing the XML string.

    Next, validate the XML string before parsing:

    • Add a Message(_custVendDC); line temporarily to inspect what’s actually being received.
    • If the string starts with a line break or whitespace, trim it using DelChr(_custVendDC, '<>',' ') or similar cleanup logic.


    Also, make sure your XML namespaces are correctly declared and matched. Your FindNodeTextWithNameSpace function is solid, just ensure the prefix and namespace match exactly what’s in the incoming XML.

    Once cleaned, your codeunit should correctly extract:

    al
    AccountNum := FindNodeTextWithNameSpace(RootNode, 'd4p1:AccountNum', 'd4p1', 'http://schemas.datacontract.org/2004/07/Dynamics.AX.Application');
    Name := FindNodeTextWithNameSpace(RootNode, 'd4p1:Name', 'd4p1', 'http://schemas.datacontract.org/2004/07/Dynamics.AX.Application');
    
    
    If you still get empty values, try printing the full XML tree using RootNode.AsXmlElement.InnerXml to confirm the structure. 
     

    Helpful Reference
    SOAP Web Services in BC – Microsoft Learn
    Handling Namespaces in XMLNode – Dynamics Community


    If you find this helpful, feel free to mark this as the suggested or verified answer.

    Cheers
    Jeffrey

  • Suggested answer
    Rishabh Kanaskar Profile Picture
    3,441 on at
    SOAP Request and passing the XML values to codeunit
    Hi,
     
    The error occurs because your AL procedure is expecting a plain text XML in the _custVendDC parameter, but the SOAP request wraps it in an additional XML element with namespaces. Business Central SOAP codeunits do not automatically unwrap complex nested XML; they treat _custVendDC as a Text type, so any XML nodes above it (the SOAP envelope, body, and <saveCustVend> element) are not part of _custVendDC.
     
    To fix this:
     
    Change the parameter type from Text to XmlDocument:
    procedure saveCustVend(_custVendDC: XmlDocument): Text
    var
        RootNode: XmlNode;
        AccountNum: Text[20];
        Name: Text[100];
    begin
        RootNode := _custVendDC.AsXmlNode;
        AccountNum := RootNode.SelectSingleNode('//d4p1:AccountNum', 'd4p1=http://schemas.datacontract.org/2004/07/Dynamics.AX.Application').AsXmlElement.InnerText;
        Name := RootNode.SelectSingleNode('//d4p1:Name', 'd4p1=http://schemas.datacontract.org/2004/07/Dynamics.AX.Application').AsXmlElement.InnerText;
        exit('AccountNum: ' + AccountNum + ', Name: ' + Name);
    end;

    When calling via SOAP, pass the inner <_custVendDC> XML as a XmlDocument. You don’t need to parse the entire envelope manually; BC will map the _custVendDC element to the XmlDocument parameter.
     
    Ensure your XmlNamespaceManager or XPath query includes the d4p1 namespace exactly as in the incoming XML.
     
    This approach avoids “Data at the root level is invalid” errors because the AL procedure now directly receives a valid XML document instead of a raw string containing the SOAP wrapper.
     
    Once this works, you can later extend the procedure to create or update a customer using the extracted fields.
     
    Thanks
    Rishabh
  • Khushbu Rajvi. Profile Picture
    19,131 Super User 2025 Season 2 on at
    SOAP Request and passing the XML values to codeunit
  • Gerardo Rentería García Profile Picture
    23,558 Most Valuable Professional on at
    SOAP Request and passing the XML values to codeunit

Under review

Thank you for your reply! To ensure a great experience for everyone, your content is awaiting approval by our Community Managers. Please check back later.

Helpful resources

Quick Links

Responsible AI policies

As AI tools become more common, we’re introducing a Responsible AI Use…

Abhilash Warrier – Community Spotlight

We are honored to recognize Abhilash Warrier as our Community Spotlight honoree for…

Leaderboard > Small and medium business | Business Central, NAV, RMS

#1
Nimsara Jayathilaka. Profile Picture

Nimsara Jayathilaka. 3,846

#2
Rishabh Kanaskar Profile Picture

Rishabh Kanaskar 3,157

#3
Sumit Singh Profile Picture

Sumit Singh 2,903

Last 30 days Overall leaderboard

Featured topics

Product updates

Dynamics 365 release plans