So, this is a really interesting integration aspect between AX and .NET apps. We want to access AX business logic (or data, transactions, etc.) from the .NET world. :-)

Requirements

Before starting to develop anything, we need to install several required components:

In my case, I’ve got a single development machine where I have installed everything. I mean:

-       SQL Server 2005

-       Dynamics AX 4.0

-       AX .NET Business Connector

-       Visual Studio 2005 (for .NET development)

-       We could also install ‘Windows SharePoint Services’ and the ‘AX Enterprise Portal’. It also uses .NET Business Connector for accessing AX, but in this case, we are just  talking about .NET and AX. I’ll maybe post about ‘AX Enterprise Portal’ and Windows SharePoint Services in another posting. J

So!, the AX .NET Business Connector allows accessing Microsoft Dynamics AX from our own .NET applications as though they were a native Microsoft Dynamics AX client. So any .NET app or even ASP.NET web-app could access AX business components using this connector. For instance, as I already said, the ‘AX Enterprise Portal’ (based on Windows SharePoint Services and .NET) uses .NET Business Connector to access AX business logic.

BTW, internally, all these integration technologies interact with Dynamics AX through Application Object Server (AOS), which is kind of the ‘Business Components Application Tier’ within AX architecture itself.

AX .NET Business Connector installation and configuration

Before installing Business Connector, the following must be available in the domain:

- A core Microsoft Dynamics AX installation. This installation can be completed at the same time as the Business Connector installation, or it can be done prior to this installation.

- Active Directory configured in native mode.

By default, it uses Windows authentication security (AD), so it can be also integrated with AX Enterprise Portal (based on Windows SharePoint Services, which also uses Windows security). This security authentication type is important to have it into account when accessing from our own .NET apps.

We also need a Windows domain account to act as the Business Connector Proxy. So we need to configure the Business Connector if our application requires "act-on-behalf-of" functionality for external users or users that are at times unable to connect to our application.

So, for instance, I created an account within Windows Active Directory, called MyDomain\bcproxy. That account is going to be my ‘proxy account’.

Remember to assign a password to the user, select the Password does not expire option and select the No interactive logon rights option.

(Optional) Adding the proxy account to the IIS local Windows group.

For Web applications, we must add the Business Connector proxy account to the IIS local Windows group. If you are using Windows SharePoint Services, you must also add the account to the Windows SharePoint local Windows group.

1. Open the Computer Management application (Start > Administrative Tools > Computer Management).

2. Expand the Groups folder under Local Users and Groups.

3. Add the Business Connector proxy account to the following groups:

            - IIS_WPG (IIS Worker Process Group)

            - STS_WPG (STS Worker Process Group), if running Windows SharePoint Services

(Optional) Configure the IIS application pool

For Web applications, you must associate the Business Connector proxy account to the appropriate application pool identity.

Installation of  ‘.NET Business Connector’ setup-app.

So now we are ready to install ‘.NET Business Connector’ from normal AX setup.exe DVD, but we have to select that we want to install it. ;-)

The setup’s steps and quite normal, almost just the ‘next, next’ stuff.

Configure the Business Connector Proxy User

The last step is to configure the Business Connector Proxy User within AX configuration:

1. Start Microsoft Dynamics AX (Start > All Programs > Microsoft Dynamics > Microsoft Dynamics AX 4.0 Client).

2. Open the Business Connector Proxy dialog box: Administration > Setup > Security > Business Connector Proxy.

3. In the Alias box, enter the alias. In the Network domain box, enter the domain of the user and then close the dialog box.

Implementing a sample AX class to consume it

So now we’re starting one of the fun tasks!!

We are going to implement a basic X++ class with a simple method. Just for testing.

So, within Dynamics AX client, open the AOT (Application Objects Tree):

Then, let’s create a new simple class, like the following:

So, I’ve created a very simple method called ‘Salute()’, which accepts a single string parameter (a name) and then it responds with a salutation. It is very simple, just a testing method for accessing AX from .NET world. J. Here is the Salute() method code:

X++ Code:

client server public static str Salute(str name)
{
   str salute = "Cheers " + name + "! from AX!";
   ;
   return salute;
}

Great!, very simple!. An if you are used to C# or C++, X++ it is quite similar!.

So now, we could test this method calling it from an AX JOB. But, we’re directly to execute it calling it from .NET (developing with Visual Studio 2005) through the ‘AX .NET Business Connector’.

Ok, I’ve created a simple WinForms application project called NetBcWinFormsTest. Take into account that this is just for testing. If it were a real application (.NET WinForms client as presentation layer), may be we’ll use a Web-Service or WCF-Service in between (for remote calls).

So, here we can see VS.2005 with our simple WinForms proyect, and a single Windows form with a button: 

So now, we have to add a reference to the ‘AX .NET Business Connector’ .NET assembly, which is the ‘Microsoft.Dynamics.BusinessConnectorNet.dll’.

We have to add it using the ‘Add ReferenceàBrowse’ option, selecting the physical .dll situated on:

C:\Program Files\Microsoft Dynamics AX\40\Client\Bin\Microsoft.Dynamics.BusinessConnectorNet.dll

 

Ok, now we are ready for programming some C# code (or VB.Net code, of course).

Let’s double click on our simple button, and add the following code:

A ‘using’ sentence (just like a shortcut for our C# code):

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Text;

using System.Windows.Forms;

 


using Bcn = Microsoft.Dynamics.BusinessConnectorNet;

 

namespace NetBcWinFormsTest

{

    public partial class Form1 : Form

    {

        public Form1()

        {

            InitializeComponent();

        }

 

        private void btnAccessAX_Click(object sender, EventArgs e)

        {

            // Create a BCN object                      

            Bcn.Axapta axp;

            axp = new Bcn.Axapta();

            try

            {

                // In this case there’s no need for credentials, it is taken from Winforms execution

                // because this is just a sample testing application.

                // but if it were an ASP.NET app, we should provide specific credentials.

                 axp.Logon(null, null, null, null);

            }

            catch (Exception excepn)

            {

                MessageBox.Show(excepn.ToString());

                return;

            }           

            //Calling the X++ static Method!!.

            string salutation;           

            salutation = (string)axp.CallStaticClassMethod(

                                            "CdltllDemoBcnClass",      // The class name.

                                            "Salute",                               // method's name.

                                            "CESAR");                             // Parameters.

            MessageBox.Show(salutation);

 

            axp.Logoff();

            //

            }

    }

}

Take a look to the selected code and read all the C# comments within that code.

Note that we are instancing a standard BCN object using the class (Microsoft.Dynamics.BusinessConnectorNet.Axapta), and then, when calling the ‘CallStaticClassMethod()  method,  we have to provide all the X++ class and method  information.

So!, the resulting execution in our .NET App is the following…: 

 

Not a very impressive graphics interface, but we are getting that result from within Dynamics AX business logic!! J.

Next step is getting real data from AX tables and AX business classes.

Getting AX real Data (Updated - November 28th 2007)

So, now, we're going to add a new functionality to our little .NET program. In this case, we are going to invoke AX classes to get real AX data. For instance, we're going to get data about Vendors.

Then, we add another simple button to our .NET form, and also a DataGridView where we'll show that data. It would look like the following:

image

Then, we add the following code to be triggered from our second button:

A ‘using’ sentence (just like a shortcut for our C# code):

 

private void btnAxDataAccess_Click(object sender, EventArgs e)

{

// .NET Business Connector objects

Bcn.Axapta ax;

Bcn.AxaptaRecord axRecord;

// Name of table to query.

String strTable = "VendTable";

// VendTable field names for calls to AxRecord.get_field

String strVendAccountNumField = "AccountNum";

String strVendNameField = "Name";

// Output variables for calls to AxRecord.get_Field

Object vendAccNum, vendName;

// String used to query table.

String strQuery = "select * from %1";

//Sample including WHERE clause

//strQuery = "select * from %1 where %1.vendGroup == ' my_search_criteria_here '";

try

{

// Log on to Microsoft Dynamics AX.

ax = new Bcn.Axapta();

ax.Logon(null, null, null, null);

// Create an AxaptaRecord object for the VendTable.

axRecord = ax.CreateAxaptaRecord(strTable);

// Execute the query on the table.

axRecord.ExecuteStmt(strQuery);

// DataTable creation

DataTable dt = CreateVendorDataTable();

DataRow row;

// Loop through the set of retrieved records.

while (axRecord.Found)

{

// Retrieve the record data for the

// specified fields.

vendName = axRecord.get_Field(strVendNameField);

vendAccNum = axRecord.get_Field(strVendAccountNumField);

row = dt.NewRow();

row["Name"] = vendName.ToString();

row["AccNum"] = vendAccNum.ToString();

dt.Rows.Add(row);

// Advance to the next row.

axRecord.Next();

}

// Dispose of the AxaptaRecord object.

axRecord.Dispose();

// Log off from Microsoft Dynamics AX.

ax.Logoff();

//Data-Binding with our GRID

dataGridView1.DataSource = dt;

}

catch (Exception ex)

{

// Console.WriteLine("Error encountered: {0}", e.Message);

// Take other error action as needed.

}

}

// Create an ADO.NET DataTable ‘on the fly’

public DataTable CreateVendorDataTable()

{

DataTable dt = new DataTable();

dt = new DataTable();

DataColumn vendorNameColumn;

vendorNameColumn = new DataColumn("Name");

vendorNameColumn.DataType = Type.GetType("System.String");

dt.Columns.Add(vendorNameColumn);

DataColumn vendorAccNumColumn;

vendorAccNumColumn = new DataColumn("AccNum");

vendorAccNumColumn.DataType = Type.GetType("System.String");

dt.Columns.Add(vendorAccNumColumn);

return dt;

}

So, what we are doing is using the AxaptaRecord class to select and get all the records from AX data. Keep in mind one important thing. Unlike ADO.NET, which is connectionless oriented, AX data access classes are connection-oriented. I mean, once you have selected what you want, you have to loop over it in a connected environment. In this case, what I am doing is looping through all the records and creating an ADO.NET DataTable 'on the fly' (could be within a DataSet). After having a DataTable or DataSet we could return it to any other .NET assembly or, as in this case, we just make a DataBinding with our GridView, so we show all the records.

Or course, in a real Application and depending of data volume, we should filter data based on kind of 'data pages' or 'data windows', so we won't fill a single DataTable with all the AX table data.

So, if we execute it, we'll get all that AX data!.

image

Magic between .NET and Dynamics AX?. :-)