How to change your Microsoft Dynamics GP 2010 Map Services

In recent weeks, the newsgroups have been flooded with questions about the Bing Maps service not working at the street level for addresses in Microsoft Dynamics GP 2010 - see Microsoft Dynamics GP 2010 map buttons not drilling down to the street level. While this issue is slated to be fixed in Microsoft Dynamics GP 2010 Service Pack 2, the bottom line is, it has left a bit of a bad taste in users relying on this functionality.

In addition, some users have questioned whether they can use a map service of their choice. There are a few well known services out there, for example Yahoo! Maps, Google Maps, or even some region specific services like Australia's WhereIs.com.

The good news is the Microsoft Dynamics GP community is full of individuals who are willing to share their knowledge without any restrictions and my buddy Jon Eastman at Touchstone Group, a Microsoft partner in the United Kindom offers this Dexterity based solution.

The Dexterity solution implements an AFTER trigger on the FormatWebAddress() function of the of the syMapPoint form. The processing function, GenerateGoogleMapsURL(), overrides the formatted address returned by the FormatWebAddress() function based on the address parameters. The Google Maps URL is then masked with the correct parameters and returned by the function for Microsoft Dynamics GP call to the browser application.

GenerateGoogleMapsURL()
{ function GenerateGoogleMapsURL

  Created by Jon Eastman, Touchstone Group
  This code is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 2.5 Generic license.
}
function returns string  sWebAddress;

in  string  sAddress;
in  string  sCity;
in  string  sState;
in  string  sZip;
in  string  sCountry;

sWebAddress = "http:\\maps.google.com\maps?q=" + FormatSegment(sAddress) of form syMapPoint + 
     "," + FormatSegment(sCity) of form syMapPoint + 
     "," + FormatSegment(sState) of form syMapPoint + 
     "," + FormatSegment(sZip) of form syMapPoint +
     "," + FormatSegment(sCountry) of form syMapPoint;

Finally, we need to register our function trigger in the Startup script for the Runtime Engine to recognize our integrating solution event.

Startup
{ Startup
  Created by Jon Eastman, Touchstone Group
  This code is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 2.5 Generic license.
}
local integer l_result;

l_result = Trigger_RegisterFunction(function FormatWebAddress of form syMapPoint, TRIGGER_AFTER_ORIGINAL, function GenerateGoogleMapsURL);

So, I figured, this is way cool! So why not implement the Visual Studio Tools for Microsoft Dynamics GP version of it? This would give me a chance to showcase the new event registration methods for functions and procedures.

The following C# code shows the event registration using Visual Studio Tools, but this time using Yahoo! Maps:

using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Dexterity.Bridge;
using Microsoft.Dexterity.Applications;
using Microsoft.Dexterity.Applications.DynamicsDictionary;

namespace sampleMapService
{
    public class GPAddIn : IDexterityAddIn
    {
        // IDexterityAddIn interface
        SyMapPointForm mapService;

        public void Initialize()
        {
            Dynamics.Forms.SyMapPoint.Functions.FormatWebAddress.InvokeAfterOriginal += new SyMapPointForm.FormatWebAddressFunction.InvokeEventHandler(FormatWebAddress_InvokeAfterOriginal);

        }

        void FormatWebAddress_InvokeAfterOriginal(object sender, SyMapPointForm.FormatWebAddressFunction.InvokeEventArgs e)
        {
            mapService = Dynamics.Forms.SyMapPoint;

            e.result = "http:\\\\maps.yahoo.com\\map?q1=" + mapService.Functions.FormatSegment.Invoke(e.inParam1) + 
                        "+" + mapService.Functions.FormatSegment.Invoke(e.inParam2) +
                        "+" + mapService.Functions.FormatSegment.Invoke(e.inParam3) + 
                        "+" + mapService.Functions.FormatSegment.Invoke(e.inParam4) +
                        "+" + mapService.Functions.FormatSegment.Invoke(e.inParam5);

        }
    }
}

In the above code, we register an InvokeAfterOriginal event, which is very similar to the trigger registration created in Dexterity. Once the event is registered, the actual method, FormatWebAddress_InvokeAfterOriginal() is implemented by reformatting the web address using the event arguments passed by Microsoft Dynamics GP to our method.

Hope you find these two approaches useful. For more information on these development methods, please visit the Learning Resources page on this blog or visit Developing for Dynamics GP.

Downloads

VST Google Maps solution - Click here
VST Yahoo! Maps solution - Click here
VST Sample Map Service Source Code - Click here

Until next post!

MG.-
Mariano Gomez, MVP
Maximum Global Business, LLC
http://www.maximumglobalbusiness.com/

Comments

Unknown said…
Old post but commenting anyways.
Was looking at this addin but have an issue with one line.

It doesn't like the void FormatWebAddress_InvokeAfterOriginal(object sender, SyMapPointForm.FormatWebAddressFunction.InvokeEventArgs e)

Says that the InvokeEventArgs does not exist in the type....what's the reason behind that? Am I missing a reference?
Mariano Gomez said…
Tyler,

I newer versions of the .NET Framework, the event handler method does not need to be new() up. In addition, C# 6.0 furthermore force you into typing the handling method (public, private, etc.). The following should work:

public void Initialize()
{
Dynamics.Forms.SyMapPoint.Functions.FormatWebAddress.InvokeAfterOriginal += FormatWebAddress_InvokeAfterOriginal;
}

private void FormatWebAddress_InvokeAfterOriginal(object sender, SyMapPointForm.FormatWebAddressFunction.InvokeEventArgs e)
{
mapService = Dynamics.Forms.SyMapPoint;

e.result = "http:\\\\maps.yahoo.com\\map?q1=" + mapService.Functions.FormatSegment.Invoke(e.inParam1) +
"+" + mapService.Functions.FormatSegment.Invoke(e.inParam2) +
"+" + mapService.Functions.FormatSegment.Invoke(e.inParam3) +
"+" + mapService.Functions.FormatSegment.Invoke(e.inParam4) +
"+" + mapService.Functions.FormatSegment.Invoke(e.inParam5);
}

Popular posts from this blog

DBMS: 12 Microsoft Dynamics GP: 0 error when updating to Microsoft Dynamics GP 2013 R2

Do I have to use those "Z-" currency IDs in GP?

Microsoft Dynamics GP Scrolling Windows and Line Sequence Numbers