Andosi Blog - the Art of Great Design

Create a Vendor in Dynamics GP 2010 with eConnect using In Memory Serialization

Developing several integrations between Microsoft Dynamics GP 2010 and various third-party systems the last few weeks reminded me to update my previous article on In Memory Serialization for eConnect 10.
Microsoft Dynamics GP 2010 uses eConnect version 11 which includes significant updates. Notably, the COM+ component has been changed to a WCF service.
In this example, I am creating a new vendor record in Dynamics GP using the same in memory serialization technique. Why write a file to disk unnecessarily?
To run the following code on your machine:

  1. Install the latest version of the eConnect 11 SDK.
  2. Create a new Console Application in Microsoft Visual Studio.
Add references to these dynamic link libraries which are located by default in C:\Program Files (x86)\Microsoft Dynamics\eConnect 11.0\API\. (Ignore the x86 if you are using a 32-bit system.)
  1. Microsoft.Dynamics.GP.eConnect.dll
  2. Microsoft.Dynamics.GP.eConnect.Serialization.dll
Replace the Program.cs class in the project for the new class below.

using System;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
using Microsoft.Dynamics.GP.eConnect;
using Microsoft.Dynamics.GP.eConnect.Serialization;
 
class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("Beginning integration test.");
 
        using (eConnectMethods eConnectMethods = new eConnectMethods())
        {
            try
            {
                Console.WriteLine("Creating a new customer.");
 
                // Modify the connection string for your environment.
                string connectionString = @"data source=localhost; initial catalog=TWO; integrated security=SSPI";
 
                // Create the vendor.
                taUpdateCreateVendorRcd vendor = new taUpdateCreateVendorRcd();
 
                // Assign the vendor to a new master vendor type.
                PMVendorMasterType vendorType = new PMVendorMasterType();
                vendorType.taUpdateCreateVendorRcd = vendor;
 
                // Assign the master vendor type to a new 
                // collection of master vendor types.
                PMVendorMasterType[] masterVendorTypes = { vendorType };
 
                // Serialize the master vendor type in memory.
                eConnectType eConnectType = new eConnectType();
                MemoryStream memoryStream = new MemoryStream();
                XmlSerializer xmlSerializer = new XmlSerializer(eConnectType.GetType());
 
                // Assign the master vendor types to the eConnectType.
                eConnectType.PMVendorMasterType = masterVendorTypes;
 
                // Serialize the eConnectType.
                xmlSerializer.Serialize(memoryStream, eConnectType);
 
                // Reset the position of the memory stream to the start.              
                memoryStream.Position = 0;
 
                // Create an XmlDocument from the serialized eConnectType in memory.
                XmlDocument xmlDocument = new XmlDocument();
                xmlDocument.Load(memoryStream);
                memoryStream.Close();
 
                // Call eConnect to process the XmlDocument.
                eConnectMethods.CreateEntity(connectionString, xmlDocument.OuterXml);
 
                Console.WriteLine("Successfully created vendor {0}.", vendor.VENDORID);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Exception occured: " + ex.Message);
            }
            finally
            {
                eConnectMethods.Dispose();
            }
        }
 
        Console.WriteLine("Integration test complete." +
                           Environment.NewLine +
                           Environment.NewLine);
        Console.WriteLine("Press <Enter> to continue...");
        Console.ReadLine();
    }
}
Execute the project and you should see the following output:
And you should see the vendor created in Dynamics GP:
This blog has been relocated from http://mbsguru.blogspot.com/ with authorization.

Dynamics GP ActiveX component can't create object run-time error 429

Recently I was asked to look into an error a client was receiving while standing up a new Citrix server installation for their Dynamics GP 9 clients:
 

NOTE: If you are recieving this error while attempting to upgrade from Dynamics GP 9 to Dynamics GP 10, see this article.
 
When we hit the debug button to look at the underlying VBA code, we saw this line:
 

Based on the line of VBA code above, I knew that a connection to a database was needed, and the RetrieveGlobals9.dll was not installed on the new Citrix server. You might see slightly different code in your VBA, but the important part was that it was trying to call CreateObject on RetreiveGlobals9.
 
The first step to solve this problem was to download a copy of RetrieveGlobals9.dll from Partner Source at this URL.
Contact your partner to download this for you if you don't have access to Partner Source. Place the file into the Microsoft Dynamics GP folder in the Program Files directory. Since this was a 64-bit machine, the Microsoft Dynamics GP folder was in Program Files (x86).
 
Next, open a command prompt in elevated mode.
 
Finally, to register the .dll, type:
Regsvr32 "C:\Program Files (x86)\Microsoft Dynamics\GP\RetrieveGlobals9.dll"
 
You will need to include the quotes because the directories have spaces in them.
 
If everything worked properly, you'll receive a confirmation that the .dll was registered successfully.
 
 
After these steps were complete, we were able to open and use Microsoft Dynamics GP without receiving the initial VBA error.
Hope it helps!
This blog has been relocated from http://mbsguru.blogspot.com/ with authorization.

Creating Customer Invoices using Sql Server Reporting Services 2008 R2

Recently I was tasked with creating a customer facing invoice using Sql Server Reporting Services 2008 R2. This particular client had employed a technique using Page Headers and Footers that didn't upgrade properly once they moved to hosting their reports in SharePoint 2010 Integrated mode.

 
Because Page Headers and Page Footers are not allowed to have references to data fields, the main issue was with how to consistently place a totals section in a fixed position at the bottom of the page without using a Page Footer.
 
Making the task even more difficult was the fact that this report should generate all customer invoices at once. Page numbering had to be based on the individual invoice, not the total pages in the "report". Although SSRS 2008 R2 has introduced a new method to reset page numbers on a group, explained by Chris Hays here, I choose to generate my page numbers in SQL rather than in SSRS.
 
Each one of these techniques deserves a deep dive, but in general this report was accomplished by:
  • Using SQL Server window aggregate functions to both limit the number of invoice lines which should be presented on each page and to serve up the page numbers to be grouped upon and used in the display. Read this for more information: Aggregate Functions
  • Using one large cell of a table containing rectangles and a nested table for the order lines.
  • Fixing the report totals section at the proper location at the bottom of the report.
My idea was that I would limit the number of invoice line items to around 10 per page with my Sql generated page numbers. The report would be grouped by invoice number and page number. I would leave enough whitespace for those 10 lines to grow into therefore the information at the bottom of the report could be fixed just like a page footer.
 
I was having a difficult time initially getting this to work properly because the "footer" was getting pushed to the second page when the number of lines would grow. After some research, I discovered that the behavior for consuming whitespace has been changed in SSRS 2008 R2. See this article for details: Behavior Changes in Sql Server Reporting Services 2008 R2
 
Here is the important part:
 

Preserving White Space in a Report Body or Rectangle Container

Extra white space is no longer removed by default. When you render a report that had extra white space on the report body when viewed on the report design surface, the trailing white space after the last report item on the page is preserved. This may result in more pages for an existing report. To remove the white space, set the report property ConsumeContainerWhitespace to true.

 
Once I changed the ConsumerContainerWhitespace property to true, the report worked as I expected.
This blog has been relocated from http://mbsguru.blogspot.com/ with authorization.

Microsoft Dynamics 10 eConnect C# 4.0 .NET Serialization In Memory

*Note* - This code was written for Dynamics GP 10. If you are using Dynamics GP 2010 see this updated article.
I was recently tasked with creating an eConnect integration between Microsoft Dynamics GP 10 and a custom SharePoint 2010 Portal designed to replace the GP Item Maintenance process with workflow and departmental routing.

 

Most of the eConnect examples I see online serialize the eConnect object to a file before loading it into an XmlDocument. This can cause unnecessary permissions concerns, and worse, if your application runs under the context of IIS or SharePoint you may not have a file system available to you at all. This was the case in my scenario. A much better approach is to serialize the object in memory.

 
Below is an example of eConnect serialization in memory using Microsoft C# .NET 4.0.
 
Assuming you have already installed the eConnect SDK 10, reference the following assemblies:
 
Microsoft.Dynamics.GP.eConnect.dll
Microsoft.Dynamics.GP.eConnect.MiscRoutines.dll
Microsoft.Dynamics.GP.eConnect.Serialization.dll
System.EnterpriseServices.dll
 
And add the following using statements:
using System.IO;
using System.Xml;
using System.Xml.Serialization;
using Microsoft.Dynamics.GP.eConnect;
using Microsoft.Dynamics.GP.eConnect.Serialization;
Here is the code to serialize the eConnectType object in memory and load it into an XmlDocument which is then passed to the eConnect_EntryPoint method:
 
string connectionString = string.Empty; // Set up a valid connection string.

eConnectMethods econnectMethods = new eConnectMethods();
eConnectType eConnectType = new eConnectType();

// Instantiate and populate the specific eConnect types needed.
// Don't forget to add them to eConnectType once they are set up.

// We're done building the object model, now serialize it in memory.
MemoryStream memoryStream = new MemoryStream();
XmlSerializer xmlSerializer = new XmlSerializer(eConnectType.GetType());
xmlSerializer.Serialize(memoryStream, eConnectType);
memoryStream.Position = 0;

// Create a new XmlDocument from the in memory serialized object model.
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.Load(memoryStream);
memoryStream.Close();

econnectMethods.eConnect_EntryPoint(connectionString, EnumTypes.ConnectionStringType.SqlClient, xmlDocument.OuterXml, EnumTypes.SchemaValidationType.None, string.Empty);
 
Hope it helps!
This blog has been relocated from http://mbsguru.blogspot.com/ with authorization.
 
  • This email address is being protected from spambots. You need JavaScript enabled to view it.
  • (813) 792-1939
  • Privacy Policy