Options

NAV dotnet and XDocument.Descendants

thegunzothegunzo Member Posts: 274
edited 2013-08-12 in NAV Three Tier
Hi

does anyone have a solution for the XDocument.Decendants function in NAV ?

in C#
var identity = xmlDoc.Descendants(XName.Get("Identity", "http://schemas.xmlsoap.org/ws/2006/02/addressingidentity")).FirstOrDefault();

that will return identity as XElement

Don't know how to do the .FirstOrDefault

Here is the code I have tried
OBJECT Codeunit 50437 Certificate Management
{
  OBJECT-PROPERTIES
  {
    Date=11.07.13;
    Time=11:06:45;
    Modified=Yes;
    Version List=BL7.00;
  }
  PROPERTIES
  {
    OnRun=BEGIN
            MESSAGE(GetServerCertificateValue('https://ws.b2b.is/Statements/20130201/BillService.svc'));
          END;

  }
  CODE
  {

    LOCAL PROCEDURE GetWsdlContent@1000000007(wsdlUrl@1000000000 : Text) wsdlContent : Text;
    VAR
      WebClient@1000000001 : DotNet "'System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Net.WebClient";
    BEGIN
      WebClient := WebClient.WebClient;
      wsdlContent := WebClient.DownloadString(wsdlUrl);
    END;

    LOCAL PROCEDURE GetServerCertificateValue@1000000021(ServiceUrl@1000000000 : Text) encodedValue : Text;
    VAR
      xmlDoc@1000000001 : DotNet "'System.Xml.Linq, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Xml.Linq.XDocument";
      xName@1000000004 : DotNet "'System.Xml.Linq, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Xml.Linq.XName";
      Enum@1000000010 : DotNet "'System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Linq.Enumerable";
      Identities@1000000003 : DotNet "'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Collections.Generic.IEnumerable`1";
      Identity@1000000005 : DotNet "'System.Xml.Linq, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Xml.Linq.XElement";
      keyInfo@1000000007 : DotNet "'System.Xml.Linq, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Xml.Linq.XElement";
      x509Data@1000000008 : DotNet "'System.Xml.Linq, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Xml.Linq.XElement";
      x509Certificate@1000000009 : DotNet "'System.Xml.Linq, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Xml.Linq.XElement";
      wsdlUrl@1000000006 : Text;
      wsdlContent@1000000002 : Text;
    BEGIN
      wsdlUrl := ServiceUrl + '?wsdl';
      wsdlContent := GetWsdlContent(wsdlUrl);
      xmlDoc := xmlDoc.Parse(wsdlContent);
      Identities := xmlDoc.Descendants(xName.Get('Identity','http://schemas.xmlsoap.org/ws/2006/02/addressingidentity'));
      Enum := Identities.GetEnumerator;
      //Identity := Enum.FirstOrDefault(Identities);
      IF ISNULL(Identity) THEN
        ERROR(STRSUBSTNO('Unable to Parse Identity from Wsdl Content, Url:{%1}',wsdlUrl));
      keyInfo := Identity.Element(xName.Get('KeyInfo', 'http://www.w3.org/2000/09/xmldsig#'));
      IF ISNULL(keyInfo) THEN
        ERROR(STRSUBSTNO('Unable to Parse keyInfo from Wsdl Content, Url:{%1}', wsdlUrl));
      x509Data := keyInfo.Element(xName.Get('X509Data', 'http://www.w3.org/2000/09/xmldsig#'));
      IF ISNULL(x509Data) THEN
        ERROR(STRSUBSTNO('Unable to Parse keyInfo/X509Data from Wsdl Content, Url:{%1}', wsdlUrl));
      x509Certificate := x509Data.Element(xName.Get('X509Certificate', 'http://www.w3.org/2000/09/xmldsig#'));
      IF ISNULL(x509Certificate) THEN
        ERROR(STRSUBSTNO('Unable to Parse keyInfo/X509Data/x509Certificate from Wsdl Content, Url:{%1}', wsdlUrl));
      encodedValue := x509Certificate.Value;
    END;

    BEGIN
    {
      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Text;
      using System.ServiceModel;
      using System.Xml.Linq;
      using System.Security.Cryptography.X509Certificates;
      using System.Net;

      /// <summary>
              /// Gets the content of the WSDL as string.
              /// </summary>
              /// <param name="wsdlUrl">The WSDL URL.</param>
              /// <returns></returns>
              private static string GetWsdlContent(string wsdlUrl)
              {
                  try
                  {
                      using (WebClient client = new WebClient())
                      {
                          var wsdlContent = client.DownloadString(wsdlUrl);
                          return wsdlContent;
                      }
                  }
                  catch (Exception ex)
                  {
                      throw new Exception(string.Format("Unable to Download Wsdl, Url:{0}, {1}", wsdlUrl, ex.Message), ex);
                  }
              }


      public static string GetServerCertificate(string address)
              {
                  var wsdlUrl = string.Concat(address, "?wsdl");
                  var wsdlContent = GetWsdlContent(wsdlUrl);
                  try
                  {
                      var xmlDoc = XDocument.Parse(wsdlContent);
                      var identity = xmlDoc.Descendants(XName.Get("Identity", "http://schemas.xmlsoap.org/ws/2006/02/addressingidentity")).FirstOrDefault();
                      if (identity == null)
                      {
                          throw new Exception(string.Format("Unable to Parse Identity from Wsdl Content, Url:{0}", wsdlUrl));
                      }
                      var keyInfo = identity.Element(XName.Get("KeyInfo", "http://www.w3.org/2000/09/xmldsig#"));
                      if (keyInfo == null)
                      {
                          throw new Exception(string.Format("Unable to Parse keyInfo from Wsdl Content, Url:{0}", wsdlUrl));
                      }
                      var x509Data = keyInfo.Element(XName.Get("X509Data", "http://www.w3.org/2000/09/xmldsig#"));
                      if (x509Data == null)
                      {
                          throw new Exception(string.Format("Unable to Parse keyInfo/X509Data from Wsdl Content, Url:{0}", wsdlUrl));
                      }
                      var x509Certificate = x509Data.Element(XName.Get("X509Certificate", "http://www.w3.org/2000/09/xmldsig#"));
                      if (x509Certificate == null)
                      {
                          throw new Exception(string.Format("Unable to Parse keyInfo/X509Data/x509Certificate from Wsdl Content, Url:{0}", wsdlUrl));
                      }
                      var encodedValue = x509Certificate.Value;
                  }
                  catch (Exception ex)
                  {
                      throw new Exception(string.Format("Unable to Parse Wsdl Content, Url:{0}, {1}", wsdlUrl, ex.Message), ex);
                  }
                  return encodedValue;
              }
    }
    END.
  }
}

________________________________
Gunnar Gestsson
Microsoft Certified IT Professional
Dynamics NAV MVP
http://www.dynamics.is
http://Objects4NAV.com

Comments

  • Options
    mdPartnerNLmdPartnerNL Member Posts: 802
    Could you first show a short example of the data in de xml, and what values you are trying to get
  • Options
    thegunzothegunzo Member Posts: 274
    The source wsdl url is in the code example
    ________________________________
    Gunnar Gestsson
    Microsoft Certified IT Professional
    Dynamics NAV MVP
    http://www.dynamics.is
    http://Objects4NAV.com
  • Options
    Igor_PchelnikovIgor_Pchelnikov Member Posts: 25
    Hello,
    NAV doesn't support linq extensions [-X
    You might need to find another approach doing this. Or you can try to find the way using enumerator and casting object. Haven't tried myself and seems might be also dead end.

    Igor Pchelnikov
  • Options
    thegunzothegunzo Member Posts: 274
    Thank you Igor for clearing this up.

    A custom .dll is the solution then...
    ________________________________
    Gunnar Gestsson
    Microsoft Certified IT Professional
    Dynamics NAV MVP
    http://www.dynamics.is
    http://Objects4NAV.com
  • Options
    Dirk_BourgeoisDirk_Bourgeois Member Posts: 6
    edited 2018-01-10
    Uhm.. guys? This works just fine: (NAV 2015)

    Name DataType Subtype Length
    XDocument DotNet System.Xml.Linq.XDocument.'System.Xml.Linq, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'
    XName DotNet System.Xml.Linq.XName.'System.Xml.Linq, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'
    IEnumerable DotNet System.Collections.IEnumerable.'mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'
    IEnumerator DotNet System.Collections.IEnumerator.'mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'
    XElement DotNet System.Xml.Linq.XElement.'System.Xml.Linq, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'
    XAttribute DotNet System.Xml.Linq.XAttribute.'System.Xml.Linq, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'



    LOCAL ParseXmlValue(XmlContent : Text) Value : Text
    XDocument := XDocument.XDocument();
    XDocument := XDocument.Parse(XmlContent);
    IEnumerable := XDocument.Descendants(XName.Get('Data', Namespace));
    IEnumerator := IEnumerable.GetEnumerator();
    IEnumerator.MoveNext();
    XElement := IEnumerator.Current();
    XAttribute := XElement.Attribute(XName.Get('Type', Namespace));
    exit(XElement.Value +' ; '+ XAttribute.Value);
Sign In or Register to comment.