Developing for Dynamics GP

by David Musgrave (Perth, WA, Australia) and the Microsoft Dynamics GP Developer Support Team (Fargo, ND, USA)

Creating a Custom Serialization Assembly for eConnect for Microsoft Dynamics GP 2010

Creating a Custom Serialization Assembly for eConnect for Microsoft Dynamics GP 2010

  • Comments 7

Chris Roehrich - Click for blog homepageThe eConnect Programmer's guide discusses creating a custom XML node and stored procedure so developers can process new types of data.   For example, a custom or 3rd party table could be updated when integrating a master record like a Customer or a transaction like a Sales Invoice using eConnect.   The strategy that I will discuss below is for developers out there that would like to go one step further by referencing their own custom assembly.  This assembly can be referenced in their Visual Studio project which would allow them to serialize the eConnect XML document with the custom node.  

In the "Custom XML Nodes" section of the eConnect Programmers guide, the custom stored procedure is named eConnectCustomProcedure.  It has one input parameter named CUSTNMBR that holds a Customer ID value.  The custom XML node would look like this:

    <eConnectCustomProcedure>
      <CUSTNMBR>AARONFIT0001</CUSTNMBR>
    </eConnectCustomProcedure>

To use your custom XML node you will need to include this in a eConnect XML document like the following: 

<eConnect xmlns:dt="urn:schemas-microsoft-com:datatypes">
    <RMCustomerMasterType>
        <eConnectProcessInfo>
            <eConnectProcsRunFirst>TRUE</eConnectProcsRunFirst>
        </eConnectProcessInfo>
        <eConnectCustomProcedure>
            <CUSTNMBR>CONTOSOL0002</CUSTNMBR>
        </eConnectCustomProcedure>
        <taUpdateCreateCustomerRcd>
            <CUSTNMBR>CONTOSOL0002</CUSTNMBR>
            <CUSTNAME>Contoso, Ltd.</CUSTNAME>
            <TAXSCHID>USALLEXMPT-0</TAXSCHID>
            <ADRSCODE>PRIMARY</ADRSCODE>
            <ADDRESS1>321 Main S </ADDRESS1>
            <CITY>Valley City</CITY>
            <STATE>ND</STATE>
            <ZIPCODE>56789</ZIPCODE>
            <COUNTRY>USA</COUNTRY>
            <PHNUMBR1>13215550100</PHNUMBR1>
            <PHNUMBR2>13215550110</PHNUMBR2>
            <FAX>13215550120</FAX>           
        </taUpdateCreateCustomerRcd>
    </RMCustomerMasterType>
</eConnect>

The question is how can we serialize a document like this in our Visual Studio project when the existing eConnect serialization assembly does not know anything about the custom node?  The answer is we will create a new assembly that we can reference in the Visual Studio project.   This approach allows the developer to follow the pattern of working with the types in the serialization assembly like we provide in the eConnect documentation and SDK samples.

The first step I did was edit the RMCustomerMaster.xsd file located under the C:\Program Files (x86)\Microsoft Dynamics\eConnect 11.0\XML Sample Documents\Incoming XSD Individual Schemas folder.  I used Visual Studio 2010 for this step over Notepad since it is easier to read.  I added a new element called eConnectCustomProcedure for the RMCustomerMasterType complex type like below:

 <xs:complexType name="RMCustomerMasterType">
    <xs:sequence>
      <xs:element minOccurs="0" maxOccurs="1" name="eConnectProcessInfo" nillable="true" type="eConnectProcessInfo" />
      <xs:element minOccurs="0" maxOccurs="1" name="taRequesterTrxDisabler_Items" nillable="true" type="taRequesterTrxDisabler_Items" />
      <xs:element minOccurs="0" maxOccurs="1" name="taUpdateCreateCustomerRcd" nillable="true" type="taUpdateCreateCustomerRcd" />
      <xs:element minOccurs="0" maxOccurs="1" name="taCreateCustomerAddress_Items" nillable="true" type="taCreateCustomerAddress_Items" />
      <xs:element minOccurs="0" maxOccurs="1" name="taCreateInternetAddresses_Items" nillable="true" type="taCreateInternetAddresses_Items" />
      <xs:element minOccurs="0" maxOccurs="1" name="taCreateParentID" nillable="true" type="taCreateParentID" />
      <xs:element minOccurs="0" maxOccurs="1" name="taParentIDChild_Items" nillable="true" type="taParentIDChild_Items" />
      <xs:element minOccurs="0" maxOccurs="1" name="eConnectCustomProcedure" nillable="true" type="eConnectCustomProcedure" />
    </xs:sequence>
  </xs:complexType>

I then added a new complex type near the bottom of the file right above the </ xs:schema> end tag.   I used the below string type for the CUSTNMBR parameter that the custom procedure needs like below:

 <xs:complexType name="eConnectCustomProcedure">
    <xs:sequence>
      <xs:element minOccurs="1" maxOccurs="1" name="CUSTNMBR" type="xs:string" />
    </xs:sequence>
  </xs:complexType>
</xs:schema>

Next I used the xsd.exe tool to build a new class based on the XSD file.  I used the below syntax at a command prompt in the C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC directory.  This is the Microsoft Visual Studio Command Prompt for Visual Studio 2010 that is available in the Microsoft Visual Studio 2010 program folder.  

 xsd "C:\eConnectDev\RMCustomerMaster.xsd" /c

This step creates a class file named RMCustomerMaster.cs in the C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC folder.   I added the new class file to a Visual Studio 2010 C# library project named RMCustomerCustomECONNECT that used a default namespace of RMCustomerCustomECONNECT.  You could modify the code in the class file to add your own custom namespace but I left it alone using just the default from Visual Studio 2010.  After building the project in Visual Studio 2010 it created an assembly named RMCustomerCustomECONNECT.dll. 

Lastly, I made a reference to this new assembly and the Microsoft.Dynamics.GP.eConnect.dll assembly in my eConnect project.   This is a C# Console Application that serializes the XML document with the custom node and passes it to the CreateEntity method of the eConnectMethods class.  The code looks like the following:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Microsoft.Dynamics.GP.eConnect;
using System.Xml;
using System.Xml.Serialization;
using System.IO;

namespace CreateCustomerWithECONNECTCustomXML
{
    class Program
    {
        static void Main(string[] args)
        {
            using (eConnectMethods eConCall = new eConnectMethods())
            {
                try
                {
                    // Create the eConnect document and store it in a file
                    SerializeCustomerObject("customer.xml");

                    // Load the eConnect XML document from the file into
                    // an XML document object
                    XmlDocument xmldoc = new XmlDocument();
                    xmldoc.Load("customer.xml");

                    // Create an XML string from the document object
                    string customerDocument = xmldoc.OuterXml;

                    // Create a connection string
                    //Integrated Security is required. Integrated security=SSPI
                    string sConnectionString = "data source=croehric1\\sqlexpress;initial catalog=TWO;integrated security=SSPI;persist security info=False;packet size=4096";

                    // Use the eConnect_EntryPoint method to create the sales document in Microsoft Dynamics GP
                    // The XML string is not validated by the method call
                    eConCall.CreateEntity(sConnectionString, customerDocument);
                }
                // The eConnectException class will catch any business logic related errors from eConnect_EntryPoint.
                catch (eConnectException exp)
                {
                    Console.Write(exp.ToString());
                }
                // Catch any system error that might occur. Display the error to the user
                catch (Exception ex)
                {
                    Console.Write(ex.ToString());
                }
                Console.WriteLine("-----");
                Console.WriteLine("Press Enter to quit.");
                Console.ReadLine();
            }

        }

         private static void SerializeCustomerObject(string filename)
        {
            try
            {

                RMCustomerMasterType rmCustomerMasterType = new RMCustomerMasterType();
                eConnectProcessInfo procInfo = new eConnectProcessInfo();
                taUpdateCreateCustomerRcd customerRecord = new taUpdateCreateCustomerRcd();
                eConnectCustomProcedure customProcNode = new eConnectCustomProcedure();

                customerRecord.CUSTNMBR = "AARONFIT0001";
                customerRecord.UpdateIfExists = 1;

                customProcNode.CUSTNMBR = customerRecord.CUSTNMBR;

                rmCustomerMasterType.taUpdateCreateCustomerRcd = customerRecord;
                rmCustomerMasterType.eConnectCustomProcedure = customProcNode;
                procInfo.ProductName = "eConnect Test";
                rmCustomerMasterType.eConnectProcessInfo = procInfo;

                eConnectType eConnect = new eConnectType();
                RMCustomerMasterType[] MyCustomerTransactionType = { rmCustomerMasterType };
                eConnect.RMCustomerMasterType = MyCustomerTransactionType;

                // Create a file to hold the serialized eConnect XML document
                FileStream fs = new FileStream(filename, FileMode.Create);
                XmlTextWriter writer = new XmlTextWriter(fs, new UTF8Encoding());

                // Serialize the eConnect document object to the file using the XmlTextWriter.
                XmlSerializer serializer = new XmlSerializer(eConnect.GetType());
                serializer.Serialize(writer, eConnect);
                writer.Close();
            }
            //If an eConnect exception occurs, notify the user
            catch (eConnectException ex)
            {
                Console.Write(ex.ToString());
            }

        }
    }
}

// Copyright © Microsoft Corporation.  All Rights Reserved.
// This code released under the terms of the
// Microsoft Public License (MS-PL, http://opensource.org/licenses/ms-pl.html.)

I hope this post helps if you need to use custom XML nodes with your eConnect integrations.

Chris

  • Posting from Mariano Gomez, The Dynamics GP Blogster

    dynamicsgpblogster.blogspot.com/.../custom-serialization-assemblies-for.html

  • Posting from Mark Polino at DynamicAccounting.net

    msdynamicsgp.blogspot.com/.../creating-custom-serialization-assembly.html

  • The ANSI and FIPS to County and State Code database will give you the key data to link standards ANSI and FIPS codes to each County and State.

  • Is this possible in econnect10?

    This is exactly what my client needs, I just want to know if its possible in their current version.

  • Hi Chris

    This is possible to do for version 10.

    Thanks,

    Chris

  • Hi I am providing a solution to create a XML for multiple customer by using database table

    //---------------------------------------------------------------------
    //
    // Summary: This Sample creates a customer.xml document and passes it to the Microsoft.Dynamics.GP.eConnect assembly.
    //
    // Sample: eConnect_CSharp_ConsoleApplication.
    //
    //---------------------------------------------------------------------
    // This file is part of the Microsoft Dynamics GP eConnect Samples.
    //
    // Copyright (c) Microsoft Corporation. All rights reserved.
    //
    // This source code is intended only as a supplement to Microsoft Dynamics GP
    // eConnect version 11.0.0.0 release and/or on-line documentation. See these other
    // materials for detailed information regarding Microsoft code samples.
    //
    // THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
    // KIND, WHETHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
    // IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
    // PURPOSE.
    //---------------------------------------------------------------------
    using System;
    using System.IO;
    using System.Xml;
    using System.Text;
    using System.Xml.Serialization;
    using Microsoft.Dynamics.GP.eConnect;
    using Microsoft.Dynamics.GP.eConnect.Serialization;
    using System.Data.SqlClient;
    using System.Data;
    using System.Configuration;
    namespace eConnect_CSharp_ConsoleApplication
    {
       class Test
       {
           /// <summary>
           /// The main entry point for the application.
           /// </summary>
           [STAThread]
           static void Main()
           {
               string sCustomerDocument;
               string sXsdSchema;
               string sConnectionString;
               using (eConnectMethods e = new eConnectMethods())
               {
                   try
                   {
                       // Create the customer data file
                       SerializeCustomerObject("Customer.xml");
                       XmlDocument xmldoc = new XmlDocument();
                       xmldoc.Load("Customer.xml");
                       sCustomerDocument = xmldoc.OuterXml;
                       // Specify the Microsoft Dynamics GP server and database in the connection string
                       sConnectionString = @"data source=localhost;initial catalog=AP;integrated security=SSPI;persist security info=False;packet size=4096";
                       // Create an XML Document object for the schema
                       XmlDocument XsdDoc = new XmlDocument();
                       // Create a string representing the eConnect schema
                       sXsdSchema = XsdDoc.OuterXml;
                       // Pass in xsdSchema to validate against.
                       e.CreateEntity(sConnectionString, sCustomerDocument);
                   }
                   // The eConnectException class will catch eConnect business logic errors.
                   // display the error message on the console
                   catch (eConnectException exc)
                   {
                       Console.Write(exc.ToString());
                   }
                   // Catch any system error that might occurr.
                   // display the error message on the console
                   catch (System.Exception ex)
                   {
                       Console.Write(ex.ToString());
                   }
                   finally
                   {
                       // Call the Dispose method to release the resources
                       // of the eConnectMethds object
                       e.Dispose();
                   }
               } // end of using statement
           }
           public static void SerializeCustomerObject(string filename)
           {
               try
               {
                   // Instantiate an eConnectType schema object
                   eConnectType eConnect = new eConnectType();
                   // Instantiate a RMCustomerMasterType schema object
                   RMCustomerMasterType customertype = new RMCustomerMasterType();
                   // Create an XML serializer object
                   XmlSerializer serializer = new XmlSerializer(eConnect.GetType());
                   SqlConnection dbConn = new SqlConnection(ConfigurationManager.ConnectionStrings["APDev"].ConnectionString);
                   DataTable dt = new DataTable();
                   try
                   {
                       SqlCommand dbCom = new SqlCommand("GetCustomers", dbConn);
                       dbCom.CommandType = CommandType.StoredProcedure;
                       //dbCom.Parameters.Add(xmlOut);
                       dbConn.Open();
                       dt.Load(dbCom.ExecuteReader());
                   }
                   catch (Exception)
                   {
                       throw;
                   }
                   finally
                   {
                       if (dbConn != null && dbConn.State == ConnectionState.Open)
                       {
                           dbConn.Close();
                       }
                   }
                   RMCustomerMasterType[] mySMCustomerMaster = new RMCustomerMasterType[dt.Rows.Count];
                   for (int i = 0; i <= dt.Rows.Count - 1; i++)
                   {
                       DataRow dr = dt.Rows[i];
                       //// Instantiate a taUpdateCreateCustomerRcd XML node object
                       taUpdateCreateCustomerRcd customer = new taUpdateCreateCustomerRcd();
                       customer.CUSTNMBR = dr.ItemArray[0].ToString();
                       customer.CUSTNAME = dr.ItemArray[1].ToString();
                       customer.ADDRESS1 = dr.ItemArray[2].ToString();
                       customer.ADRSCODE = dr.ItemArray[3].ToString();
                       customer.CITY = dr.ItemArray[4].ToString();
                       customer.ZIPCODE = dr.ItemArray[5].ToString();
                       RMCustomerMasterType rmCustomerMasterType = new RMCustomerMasterType();
                       rmCustomerMasterType.taUpdateCreateCustomerRcd = customer;
                       mySMCustomerMaster[i] = rmCustomerMasterType;
                   }
                   eConnect.RMCustomerMasterType = mySMCustomerMaster;
                   // Create objects to create file and write the customer XML to the file
                   FileStream fs = new FileStream(filename, FileMode.Create);
                   XmlTextWriter writer = new XmlTextWriter(fs, new UTF8Encoding());
                   // Serialize the eConnectType object to a file using the XmlTextWriter.
                   serializer.Serialize(writer, eConnect);
                   writer.Close();
               }
               // catch any errors that occur and display them to the console
               catch (System.Exception ex)
               {
                   Console.Write(ex.ToString());
               }
           }
       }
    }

  • Hi Ashutosh

    Thanks for the example hopefully people will find it useful.

    David

Page 1 of 1 (7 items)
Comments Information

PLEASE READ BEFORE POSTING

Please only post comments relating to the topic of this page.

If you wish to ask a technical question, please use the links in the links section (scroll down, on right hand side) to ask on the Newsgroups or Forums. If you ask on the Newsgroups or Forums, others in the community can respond and the answers are available for everyone in the future.

Leave a Comment
  • Please add 5 and 4 and type the answer here:
  • Post