Search This Blog

Monday, July 13, 2015

AX2012 Replacing Company element value in AIF using .net dll and QueryService

Scenario:
In AIF we have some data coming from externalSystem, which externalSystem doesnt have anyinformation to which company it should load, as ExternalSystem knows the information about coRegNum as we have to find the right company in AX by using coRegNum.
Solution:
so I build a .net component where we use the dll in transformation to replace the companyelement in the header to pass the file into right company.
I am using QueryService which I querying the companyInfoTable with the range coRegNum and getting the right Company and replacing in the sourceXML in transfromation in headersection.

sample xml section below.

<ns0:Envelope xmlns:ns0="http://schemas.microsoft.com/dynamics/2011/01/documents/Message">
<ns0:Header>
<ns0:MessageId>354bcae9-45a5-411e-953f-e2920a6c0229</ns0:MessageId>
<ns0:Company>123456</ns0:Company>
<ns0:Action>http://schemas.microsoft.com/dynamics/2008/01/services/GeneralJournalService/create</ns0:Action>
</ns0:Header>
<ns0:Body>
<ns0:MessageParts>
<ns0:LedgerGeneralJournal xmlns:ns0="http://schemas.microsoft.com/dynamics/2008/01/documents/LedgerGeneralJournal" xmlns:st="http://schemas.microsoft.com/dynamics/2008/01/sharedtypes">

Before writing this class add serviceReference QueryService from AX standardservice into your solution that will create app.config as below

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <system.serviceModel>
        <bindings>
            <netTcpBinding>
                <binding name="QueryServiceEndpoint" closeTimeout="00:01:00"
                    openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
                    transactionFlow="false" transferMode="Streamed" transactionProtocol="OleTransactions"
                    hostNameComparisonMode="StrongWildcard" listenBacklog="10"
                    maxBufferPoolSize="524288" maxBufferSize="65536" maxConnections="10"
                    maxReceivedMessageSize="65536">
                    <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
                        maxBytesPerRead="4096" maxNameTableCharCount="16384" />
                    <reliableSession ordered="true" inactivityTimeout="00:10:00"
                        enabled="false" />
                    <security mode="Transport">
                        <transport clientCredentialType="Windows" protectionLevel="EncryptAndSign" />
                        <message clientCredentialType="Windows" />
                    </security>
                </binding>
            </netTcpBinding>
        </bindings>
        <client>
            <endpoint address="net.tcp://KrishhDax:8201/DynamicsAx/Services/QueryService"
                binding="netTcpBinding" bindingConfiguration="QueryServiceEndpoint"
                contract="AXQueryService.IQueryService" name="QueryServiceEndpoint">
                <identity>
                    <servicePrincipalName value="host/KrishhDax.adep01.nordic.rsa-ins.com" />
                </identity>
            </endpoint>
        </client>
    </system.serviceModel>

</configuration>

Create a tranform class which extends from Itransform.
I am using xml.linq to read the element value in the class, so I referenced System.Xml.Linq;

using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Dynamics.IntegrationFramework.Transform;
using System.Xml;
using System.Xml.Linq;
using KrishhIbanToCompanyTrans.AXQueryService;
using System.ServiceModel;
using System.Data;
using System.Net;


namespace KrishhIbanToCompanyTrans
{
    public class IBANToCompanyTrans : ITransform
    {
        public void Transform(System.IO.Stream input, System.IO.Stream output, string config)
        {
            XDocument inputXml = XDocument.Load(input);

            string accStr = inputXml.Root.Descendants().Where(e => e.Name.LocalName == "Company").First().Value;
           
            string[] serviceParams = config.Split(';');

            if (serviceParams.Count() != 1 && serviceParams.Count() != 4)
                throw new ArgumentException("Invalid configuration passed. Expecting single endpoint address or endpoint address with username, password and domain, separated by ;");

            NetTcpBinding binding1 = new NetTcpBinding();
            EndpointAddress epa = new EndpointAddress(serviceParams[0]);

            binding1.Name = "QueryServiceEndpoint";
            binding1.TransactionProtocol = TransactionProtocol.OleTransactions;
            binding1.TransferMode = TransferMode.Streamed;
            binding1.Security.Mode = SecurityMode.Transport;
            binding1.HostNameComparisonMode = HostNameComparisonMode.StrongWildcard;
            binding1.Security.Transport.ClientCredentialType =  TcpClientCredentialType.Windows;
            binding1.Security.Transport.ProtectionLevel = System.Net.Security.ProtectionLevel.EncryptAndSign;
            binding1.Security.Message.ClientCredentialType = MessageCredentialType.Windows;
            binding1.ReliableSession.Enabled = false;

            QueryServiceClient serviceClient = new QueryServiceClient(binding1, epa);

            if (serviceParams.Count() == 4)
            {
                serviceClient.ClientCredentials.Windows.ClientCredential.UserName = serviceParams[1];
                serviceClient.ClientCredentials.Windows.ClientCredential.Password = serviceParams[2];
                serviceClient.ClientCredentials.Windows.ClientCredential.Domain = serviceParams[3];
            }

            QueryMetadata query = new QueryMetadata();
            query.DataSources = new QueryDataSourceMetadata[1];
            query.Name = "CompanyInfo";
            QueryDataSourceMetadata queryDS = new QueryDataSourceMetadata();
            queryDS.Name = "CompanyInfo";
            queryDS.Table = "CompanyInfo";
            queryDS.Enabled = true;
            query.DataSources[0] = queryDS;
            queryDS.DynamicFieldList = false;
            queryDS.Fields = new QueryDataFieldMetadata[2];
            QueryDataFieldMetadata fieldId = new QueryDataFieldMetadata();
            fieldId.FieldName = "DataArea";
            fieldId.SelectionField = SelectionField.Database;
            queryDS.Fields[0] = fieldId;
            QueryDataFieldMetadata fieldName = new QueryDataFieldMetadata();
            fieldName.FieldName = "CoRegNum";
            fieldName.SelectionField = SelectionField.Database;
            queryDS.Fields[1] = fieldName;
            queryDS.Ranges = new QueryDataRangeMetadata[] { new QueryDataRangeMetadata() { TableName = "CompanyInfo", FieldName = "CoRegNum", Value = accStr, Enabled = true } };

            Paging paging = new ValueBasedPaging() { RecordLimit = 25 };



            DataSet dataset = serviceClient.ExecuteQuery(query, ref paging);
            Console.Write(dataset.GetXml());

            if (dataset != null)
            {
                if (dataset.Tables.Count > 2)
                {
                    if (dataset.Tables[3].Rows.Count > 0)
                    {
                        DataRow dr = dataset.Tables[3].Rows[0];

                        var element = inputXml.Root.Descendants().Where(e => e.Name.LocalName == "Company").First();
                        if (element != null)
                            element.Value = dr["DataArea"].ToString();
                    }
                }
            }
            inputXml.Save(output);

        }

This method is used to test the above code.
/*
        static void Main(string[] args)
        {
            IBANToCompanyTrans transformClass = new IBANToCompanyTrans();

            FileStream input, output;

            // Create the two streams to pass into the assembly. You will need to change these
            // to your file locations.
            input = new FileStream("C:\\Temp\\922\\922.xml", FileMode.Open);
            output = new FileStream("C:\\Temp\\922\\922_c.xml", FileMode.OpenOrCreate);

            string paramString = "net.tcp://hssdas115:8201/DynamicsAx/Services/QueryService";
            // Passes in the customers CSV file and gets back an XML file.
            transformClass.Transform(input, output, paramString);

            // Displays the XML to the console.
            //            StreamReader sreader = new StreamReader(new FileStream("c:\\temp\\testtmpn.xml", FileMode.Open));
            //            Console.Write(sreader.ReadToEnd());
            //            Console.ReadLine();

        } */
    }
}

After building this component, go to the inboundPort and click transformation button and go to transformations and create the .net dll  transformation and provide the dll and select the class in the dropdown.
in Config file provide the app.config file for this transformation.



No comments:

Post a Comment

Thanks for visiting my blog,
I will reply for your comment within 48 hours.

Thanks,
krishna.