This is the final part to the serieds of Importing CSV files via AIF
Part 1: Consume Web Service
Part 2: Create Item from File adapter
Part 3: Import CSV file with items Through AIF
In the past posts I consumed a webservice InventItemService and created items in the Released products. This was used as a proof of what should happen when the data is sent to Ax. Part 2 looked at doing the same thing using the File system adapter. here we created an XML file, added the item id’s and then put the file in the folder, the batch did its magic and added the items to the Released Products list
A certain drawback to the that was we had to create the XML files manually, or use an external transformer to do it. AX 2012 has a new feature where we can add transformation Libraries in the form of Either XSLT or .Net libraries.
We will be taking the Inbound port created in Part 2 of this series, and add a transformation library, and instead of dropping an XML file into the inbound directory, we will drop a CSV file
A good read about the process I am about to show is: About the AIF Pipeline [AX 2012]
Create Transformation Library
In Order to create a transformation library, we need to implement an interface found in Microsoft.Dynamics.IntegrationFramework
This DLL can be found in the directory: C:\Program Files\Microsoft Dynamics AX\60\Client\Bin\
More information about the Transformation can be found at: Walkthrough: Creating a .NET Assembly Transform [AX 2012]
What we need to do is create a Visual studio project, of a Class Library type
Add a reference to the Microsoft.Dynamics.IntegrationFramework.Dll using the link above, and create a new class which implements the interface ITransform found in Microsoft.Dynamics.IntegrationFramework.Transform.ITransform
Then create a method which implements the method Transform. This method takes in 3 parameters
1. input (System.IO.Stream) : This is the input stream which is be the file itself
2. output (System.IO.Stream marked as out): This is the output stream that will be returned back to AX. We need to populate this stream
3. configuration (string): This is a custom configuration string that can be added to the port and can be used by the transformation. in this case we will not be using it.
At this stage the class should look like this:
public class LoonItemTransform : Microsoft.Dynamics.IntegrationFramework.Transform.ITransform { public void Transform(System.IO.Stream input, System.IO.Stream output, string configuration) { //Need to populate the oputput stream here throw new NotImplementedException(); } }
Okay So we have a transformation Library, now we need to add code to read the data from the CSV file, which will be sent in the input stream as a parameter.
The CSV file we are going to add has 2 fields, the itemId and the name.
The Itemd also doubles up as the Product
The code should look like this, Its just reading a file and splitting the line contents.
public class LoonItemTransform : Microsoft.Dynamics.IntegrationFramework.Transform.ITransform { public void Transform(System.IO.Stream input, System.IO.Stream output, string configuration) { StreamReader sreader = new StreamReader(input); string[] dataArray; string lineIn = sreader.ReadLine(); while (lineIn != null) { dataArray = lineIn.Split(','); //0 is itemid, 1 is name lineIn = sreader.ReadLine(); } sreader.Close(); //Create XML for items //Serialize item data to xml string //Create Envelope and add header information, and add item data //serilalize data to outputstream } }
So at this stage we have the data from our CSV file.We now need to somehow create an XML file similar to the one we created in Part 2. For this we will taking help of the XSD files we had take earlier and I will show you how to create a .Net class out of it. We will add these classes into the Library, and populate it. Serializing these classes will give us the XML file desired.
Creating Classes from XSD
What we did in the previous part was create an XML file that conforms to a certain XSD file. There are 3 XSD files in total that we used for creating the XML file. What we well do is create classes using the XSD files, populate them using the CSV file and serialize them.Upon serialization we will get the same output as the previous post.
In our Visual studio project we will first create 2 folders (to separate the objects generated into 2 different namespaces) ItemXSD and SharedXSD
Open the Visual studio command prompt and navigate to the directory where the XSD files were saved.
For the first instance, we need to create classes for the InventItemService. This XSD (item.xsd) is dependant on the SharedTypes.xsd We will specify both these XSD files and pass it to the XSD.exe command.
In the terminal type the following command:
xsd Item.xsd SharedTypes.xsd /classes /namespace:LooneyTrans.ItemXSD
This creates a file Item_SharedTypes.cs. Place this file in the folder ItemXSD of the project
Note: If you are creating the project in VB .Net, you can use the options in XSD.exe to output a vb file instead
Now create the code for the Envelope
xsd Message.xsd /classes /namespace:LooneyTrans.SharedXSD
Place the output file Message.cs in the folder SharedXSD of the project.
After doing so we should be able to access the object AxdEntity_InventTable, just like we did in Part 1 using web services.
We need to extend this one to adding an envelope which sets the Action for the document. The code should now look like this
public class LoonItemTransform : ITransform { public void Transform(System.IO.Stream input, System.IO.Stream output, string configuration) { StreamReader sreader = new StreamReader(input); string[] dataArray; string lineIn = sreader.ReadLine(); //InventTable collection List<ItemXSD.AxdEntity_InventTable> inventTables = new List<ItemXSD.AxdEntity_InventTable>(); //List<ItemXSD.AxdEntity_InventTable> inventTables = new List<ItemXSD.AxdEntity_InventTable>(); /* There seems to be an issue with the code formatting by wordpress here. Replace 'LT' by the less than sign, and 'GT' by greater than sign. The invent table collection should be List'LT'ItemXSD.AxdEntity_InventTable'GT' inventTables = new List'LT'ItemXSD.AxdEntity_InventTable'GT'(); */ while (lineIn != null) { dataArray = lineIn.Split(','); //0 is itemid, 1 is name //Create inventTable for each line ItemXSD.AxdEntity_InventTable inventTable = new ItemXSD.AxdEntity_InventTable(); inventTable.ItemId = dataArray[0]; inventTable.Product = dataArray[0]; inventTable.NameAlias = dataArray[1]; //Insert inventTable to collection inventTables.Add(inventTable); lineIn = sreader.ReadLine(); } sreader.Close(); ItemXSD.AxdItem item = new ItemXSD.AxdItem(); item.InventTable = inventTables.ToArray(); //Serialize item data to xml string StringWriter stringWriterItems = new StringWriter(); System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(ItemXSD.AxdItem)); serializer.Serialize(stringWriterItems, item); //Put it inside the envelope SharedXSD.EnvelopeType envelope = new SharedXSD.EnvelopeType(); SharedXSD.HeaderType header = new SharedXSD.HeaderType() { MessageId = Guid.NewGuid().ToString("B"), Action = @"http://schemas.microsoft.com/dynamics/2008/01/services/ItemService/create" }; envelope.Header = header; SharedXSD.BodyType bodyType = new SharedXSD.BodyType(); //Load item data xml string into an XML Document XmlDocument xmlDocumentItems = new XmlDocument(); xmlDocumentItems.LoadXml(stringWriterItems.ToString()); //Set the body to the Item XML Document bodyType.MessageParts = xmlDocumentItems.DocumentElement; envelope.Body = bodyType; //serilalize to outputstream System.Xml.Serialization.XmlSerializer mainSerializer = new System.Xml.Serialization.XmlSerializer(typeof(SharedXSD.EnvelopeType)); mainSerializer.Serialize(output, envelope); } }
We now need to compile the project and load the resulting DLL into AX.
Loading the Transformation Library
Going back to the Previous post where we created the Inbound port using the File System Adapter, we need to tell it to use our transformation library. To do so, first deactivate the port, and then set the Inbound Transforms to true.
From the inbound transform screen, we need to add the Library to the Main Transformation Library. Click the Manage Transformsand add the Library that we created and give it a name and description. Note that you need to set a class on the Manage transforms. This means that we can have more than one transform method in the class library and create a record for each of those.
We just added our transformation to the main repository and need to reference it in the Inbound transforms for this port
Notice that the configuration is a text field which can be loaded from a file. This is the text that is passed onto the Transform method created earlier.
After activating this, we should be ready to drop our file and start out batch job
So the File we are passing in look like this:
SS001,SS1ItemName SS002,SS2ItemName
After dropping the File into the Inbound directory, the batch picks it up and pushes it into the Message Queue.
As you can see the message that has been created by the transformation Library is similar to the one we used in the Previous post.
When running the batch job again, this queue is processed and the items are pushed into the Released Product table
This concludes the series of Importing a CSV file into AX using the File System Adapter. (*tears of joy rolling out now*)
Filed under: .Net, AIF, Ax 2012, Dynamics Ax Tagged: AIF, AX2012, Dynamics Ax
