Thursday 29 January 2015

How the Connector for Dynamics consumes AX AIF Document Services

I've been working lately on integration with AX using the Application Integration Framework (AIF) and thought some might find this little code sample useful.

This example demonstrates conceptually how the Connector for Dynamics makes service calls AX to get data (without change tracking enabled). 

At a high level, the Connector for Dynamics integrates with AX by:
  1. Calling the findKeys service operation to get a collection of entity keys
  2. Iterating over the collection of keys and calling the read service operation providing each key. This ensures only one record per document is returned, for example one customer
Here is the sample code:

[TestClass]
public class AxCustomerToCrmAccountTests
{
    private readonly CallContext _callContext = new CallContext
    {
        Company = "company",
        Language = "en-US"
    };

    [TestMethod]
    public void TestShowingHowTheConnectorCallsAx()
    {

        // setup the client
        // Use the following to specify credentials otherwise:
        //      ConnCustomerOrgServiceClient client = new ConnCustomerOrgServiceClient() 
        // will do.
        ConnCustomerOrgServiceClient client = new ConnCustomerOrgServiceClient(new NetTcpBinding(),
                new EndpointAddress(new Uri("net.tcp://host:integrationport/DynamicsAx/Services/DynamicsConnectorDefaultServices")));

        string userName = @"domain\username";
        string password = "password";
        if (client.ClientCredentials != null)
        {
            client.ClientCredentials.Windows.ClientCredential = new NetworkCredential(userName, password);
        }

        using (client)
        {
            // construct the query criteria
            // Base on AxdConnCustomerOrg
            // Gets data based on modified date time of the parent datasource in the document service query
            QueryCriteria queryCriteria = new QueryCriteria
            {
                CriteriaElement = new[]
                {
                    new CriteriaElement
                    {
                        DataSourceName = "CustTable",
                        FieldName = "modifiedDateTime",
                        Operator = Operator.GreaterOrEqual,
                        Value1 = new DateTime(2015, 1, 25, 1, 0, 0).ToString("s") 
                    }
                }
            };

            // find the keys based on the query criteria
            EntityKey[] keys = client.findKeys(_callContext, queryCriteria);

            // iterate over the keys to read each document
            if (keys != null)
            {
                foreach (var entityKey in keys)
                {
                    // Get the specific message for the selected customer
                    AxdConnCustomerOrg axCustomer = client.read(_callContext, new[]
                    {
                        entityKey
                    });

                    AxdEntity_CustTable custTable = axCustomer.CustTable.First();

                    // Not a real unit test, just output some data to verify it works
                    Console.WriteLine("{0}|{1}", custTable.AccountNum, custTable.RecId);
                }
            }
        }
    }
}