#GPPT Speeding Up Referencing Modifier Added Fields and staying Web Client compatible


David Meego - Click for blog homepageUsing the method discussed in the article #GPPT Referencing Modifier Added Fields in the Web Client using .Net Execute it was possible able to get past some of the limitations mentioned in the article Dynamics.Application Object not available on Web Client.

However, running the .Net (C# or VB.Net) code is slightly slower than running the Dexterity (sanScript) code. This article explains a method of how to improve Desktop Client performance while staying compatible with the Web Client.

All scripts executed by GP Power Tools use dynamic compilation at runtime. Dexterity sanScript code running in the context of a Modified dictionary (so it can access Modifier Added Fields) uses the Dynamics.Application COM object. As the Dynamics.Application object is not available on the Web Client, we had to find an alternate method. So we used a .Net script (C# or VB.Net) with a Dictionary Assembly DLL based on the custom forms dictionary (created with the DAG.EXE tool) which allowed us to address the Modifier Added Fields.

The process of dynamic compilation does take some time, but we have found that the Dexterity compilation seems to be quicker than the .Net compilation. To leverage this performance improvement, we decided to use Dexterity on the Desktop Client and use .Net only for the Web Client.

[Edit] The upcoming GP Power Tools Build 28 no longer uses “Continuum” and so no longer is affected by the limitations this caused.

We are going to continue using the example from the recent series of articles that started with #GPPT Beginner’s Guide to Adding Custom Fields – Introduction.

The steps involved from a high level are as follows:

  1. Create Runtime Execute scripts running against Modifier Added Fields.
  2. Create Triggers to call either .Net Execute Script or Runtime Execute scripts depending on client type.
  3. Disable the previous .Net Execute script only based Triggers.

Creating the Runtime Execute Scripts

  1. From the Project Setup window open the ITEM URL READ Trigger. Select the code on the Script tab and press Ctrl-C to copy it to the clipboard.
  2. Back on the Project Setup window, select Add >> Runtime Execute Setup. Enter the Script ID: ITEM URL READ, Script Name: Read Web URL Link field to Item Maintenance Window, Select Dictionary: Microsoft Dynamics GP and select the Modified checkbox.
  3. Paste the script from the trigger into the window. Then remove all the trigger parameter related lines: declaration of err_val, IN_OldValue and IN_NewValue variables and all lines starting with “err_val =”.
  4. Click Save and close the window.
  5. From the Project Setup window open the ITEM URL SAVE Trigger. Select the code on the Script tab and press Ctrl-C to copy it to the clipboard.
  6. Back on the Project Setup window, select Add >> Runtime Execute Setup. Enter the Script ID: ITEM URL SAVE, Script Name: Save Web URL Link field from Item Maintenance Window, Select Dictionary: Microsoft Dynamics GP and select the Modified checkbox.
  7. Paste the script from the trigger into the window. Then remove all the trigger parameter related lines: declaration of err_val, IN_OldValue and IN_NewValue variables and all lines starting with “err_val =”.
  8. Click Save and close the window.

Creating the updated Triggers

  1. From the Project Setup Window, double click on the ITEM URL READ2 Trigger to open it. Click Duplicate and Name it ITEM URL READ3 and click OK.
  2. In the section underneath the modified window check where it says { Code in here }, add the line “if IsWebClient() then”, then indent the loading of the .Net Script and the execution of the .Net Script and add the lines “else” and “end if;” afterwards.
    Note: IsWebClient() is a function in the Dynamics Dictionary and might not work if the script context is not Microsoft Dynamics GP.
  3. Between the “else” and “end if;” lines, use the Helper Button to insert the Load Runtime Execute Script ID function for the ITEM URL READ script. Then insert the Execute Dexterity SanScript helper function. Remove the sample script just to leave the two helper function calls.
  4. Click Save and close the window.
  5. Repeat the above steps for the ITEM URL SAVE2 Trigger to create the ITEM URL SAVE3 Trigger. Add the if statement using the IsWebClient() function and add the call to the Runtime Execute Script ITEM URL SAVE.
  6. Click Save and close the window.

Disable the previous Triggers

  1. From the Project Setup window. Double click on the ITEM URL READ2 Trigger. Once open, select the Disabled checkbox and click Save.
  2. From the Project Setup window. Double click on the ITEM URL SAVE2 Trigger. Once open, select the Disabled checkbox and click Save.
  3. Close the Trigger Setup window.
  4. From the Project Setup window, click Start >> Start Project Triggers and test the Modified version of the Item Maintenance window on the Desktop Client. Once you are happy it is working, re-test on the Web Client.

Below is the code from the two Runtime Execute Scripts:

ITEM URL READ Runtime Execute Script

local string MBS_ObjectID;
local string MBS_Property;

if isopen(form IV_Item_Maintenance) then
	MBS_ObjectID = 'Item Number' of window 'IV_Item_Maintenance' of form 'IV_Item_Maintenance';
	call with name "MBS_DUOS_Get" in dictionary 5261, "Item", MBS_ObjectID, "URL", MBS_Property;
	
	'(L) URL' of window 'IV_Item_Maintenance' of form 'IV_Item_Maintenance' = MBS_Property;
end if;

ITEM URL SAVE Runtime Execute Script

local string MBS_ObjectID;
local string MBS_Property;

if isopen(form IV_Item_Maintenance) then
	MBS_ObjectID = 'Item Number' of window 'IV_Item_Maintenance' of form 'IV_Item_Maintenance';
	MBS_Property = '(L) URL' of window 'IV_Item_Maintenance' of form 'IV_Item_Maintenance';
	if not empty(MBS_Property) then
		call with name "MBS_DUOS_Set" in dictionary 5261, "Item", MBS_ObjectID, "URL", MBS_Property;
	else
		call with name "MBS_DUOS_Del" in dictionary 5261, "Item", MBS_ObjectID, "URL";
	end if;
end if;

Below is the code from the two new Triggers Scripts:

ITEM URL READ3 Trigger Script

in string IN_OldValue;
in string IN_NewValue;
out boolean OUT_Condition;
local integer MBS_Mode;
local text MBS_References;
local text MBS_Script;
local text MBS_Results;
local boolean MBS_Success;
local boolean MBS_Access;
local integer MBS_AltDictID;
local boolean MBS_Modified;
local text MBS_Text_Field;
local integer MBS_Dictionary;
local integer MBS_Status;

OUT_Condition = false;

if isopen(form IV_Item_Maintenance) then
	call with name "MBS_Security_Form_Check" in dictionary 5261, 0, "IV_Item_Maintenance" {Form}, 
		MBS_Access, MBS_AltDictID, MBS_Modified;
	if MBS_Access and MBS_AltDictID = 0 {Product} and MBS_Modified then 
		{ Code in here } 
		
		if IsWebClient() then
			call with name "MBS_Script_Load_Net" in dictionary 5261, 
				"ITEM URL READ", MBS_Mode, MBS_References, MBS_Script;

			MBS_Success = false;
			call with name "MBS_Net_Execute" in dictionary 5261, 
				MBS_Mode, MBS_References, MBS_Script, MBS_Results, MBS_Success;
			if not MBS_Success then
				warning MBS_Results;
			end if;
		else
			call with name "MBS_Script_Load_Dex" in dictionary 5261, 
				"ITEM URL READ", MBS_Text_Field, MBS_Dictionary;
				
			call with name "MBS_Runtime_Execute_Modified" in dictionary 5261, 
				MBS_Text_Field, MBS_Dictionary, MBS_Status;
			if MBS_Status <> OKAY then
				warning MBS_Text_Field;
			end if;
		end if;
		
		OUT_Condition = true;
	end if;
end if;

ITEM URL SAVE3 Trigger Script

in string IN_OldValue;
in string IN_NewValue;
out boolean OUT_Condition;
local boolean MBS_Access;
local integer MBS_AltDictID;
local boolean MBS_Modified;
local integer MBS_Mode;
local text MBS_References;
local text MBS_Script;
local text MBS_Results;
local boolean MBS_Success;
local text MBS_Text_Field;
local integer MBS_Dictionary;
local integer MBS_Status;

OUT_Condition = false;

if isopen(form IV_Item_Maintenance) then
	if not 'Save Record' of window IV_Item_Maintenance of form IV_Item_Maintenance then
		abort script;
	end if;

	call with name "MBS_Security_Form_Check" in dictionary 5261, 0, "IV_Item_Maintenance" {Form}, 
		MBS_Access, MBS_AltDictID, MBS_Modified;
	if MBS_Access and MBS_AltDictID = 0 {Product} and MBS_Modified then 
		{ Code in here } 
		
		if IsWebClient() then
			call with name "MBS_Script_Load_Net" in dictionary 5261, 
				"ITEM URL SAVE", MBS_Mode, MBS_References, MBS_Script;

			MBS_Success = false;
			call with name "MBS_Net_Execute" in dictionary 5261, 
				MBS_Mode, MBS_References, MBS_Script, MBS_Results, MBS_Success;
			if not MBS_Success then
				warning MBS_Results;
			end if;
		else
			call with name "MBS_Script_Load_Dex" in dictionary 5261, 
				"ITEM URL SAVE", MBS_Text_Field, MBS_Dictionary;

			call with name "MBS_Runtime_Execute_Modified" in dictionary 5261, 
				MBS_Text_Field, MBS_Dictionary, MBS_Status;
			if MBS_Status <> OKAY then
				warning MBS_Text_Field;
			end if;
		end if;

		OUT_Condition = true;
	end if;
end if;

This method improves performance on the Desktop Client will still maintaining compatibility with the Web Client.

Here is the updated exported Configuration Settings file for the example:

Hope you find this technique useful.

David

08-Apr-2020: Added comment that GP Power Tools Build 28 no longer uses “Continuum”.

This article was originally posted on http://www.winthropdc.com/blog.

2 thoughts on “#GPPT Speeding Up Referencing Modifier Added Fields and staying Web Client compatible

Please post feedback or comments

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.