This document describes a first sample implementation of a plugin in the DataMigratePro system.

1. Introduction

With the plugin architecture of DataMigratePro, external functions can be integrated into the system in a modular way. The goal is extensibility without changing the core code.

2. Development of the plugin

The following example implements the IRelayPlugin interface. The getprinter action returns a list of the locally installed printers:

using System;
using System.Text;
using System.Threading.Tasks;
using System.Collections.Generic;
using System.Drawing.Printing;
using DataMigratePro.Plugins;

namespace GetPrinterPlugin
{
    public class GetPrinterPlugin : IRelayPlugin
    {
        public string ActionName => "getprinter";

        public async Task<string> ExecuteAsync(string base64Data)
        {
            await Task.Yield(); // simulate async
            string decodedInput = Encoding.UTF8.GetString(Convert.FromBase64String(base64Data));

            var printers = new List<string>();
            foreach (string printer in PrinterSettings.InstalledPrinters)
            {
                printers.Add(printer);
            }

            var result = new
            {
                action = ActionName,
                input = decodedInput,
                printers = printers
            };

            return System.Text.Json.JsonSerializer.Serialize(result, new System.Text.Json.JsonSerializerOptions { WriteIndented = true });
        }
    }
}

🔧 Note: the plugin DLL and the DataMigratePro.Plugins.dll must be copied into the plugins subdirectory.

3. Business Central Integration

An AL page is provided for controlling the plugin; it handles the call and displays the result.

page 50100 "Relay Result Viewer"
{
    PageType = Card;
    Caption = 'Relay Result Viewer';
    ApplicationArea = All;
    UsageCategory = Administration;

    layout
    {
        area(content)
        {
            field("ActionText"; ActionText) { ApplicationArea = All; }
            field("JSON (Raw)"; RawJsonText) { ApplicationArea = All; MultiLine = true; }
            field("Response"; ResultText) { ApplicationArea = All; Editable = false; MultiLine = true; }
            field("Info"; InfoText) { ApplicationArea = All; Editable = false; Style = Attention; StyleExpr = true; }
        }
    }

    actions
    {
        area(Processing)
        {
            group(Action)
            {
                action(SendToRelay)
                {
                    Caption = 'Send to Azure Relay';
                    Image = ExecuteBatch;
                    ApplicationArea = All;
                    Promoted = true;
                    PromotedCategory = Process;
                    PromotedIsBig = true;

                    trigger OnAction()
                    var
                        Sender: Codeunit "Azure Relay Sender IOI";
                        FullJson: Text;
                        EncodedMessage: Text;
                    begin
                        Base64Data := ToBase64(RawJsonText);
                        FullJson := '{"action":"' + ActionText + '","data":"' + Base64Data + '"}';
                        EncodedMessage := ToBase64(FullJson);
                        ResultText := Sender.SendMessage(EncodedMessage);
                    end;
                }
            }
        }
    }

    trigger OnOpenPage()
    begin
        ActionText := 'getprinter';
        RawJsonText := '{}';
        InfoText :=
            'This tool sends actions to Azure Relay. ' +
            'The data will be base64 encoded and wrapped into a JSON structure like: ' +
            '{"action":"...","data":"..."}, then encoded again before sending.';
    end;

    var
        ActionText: Text;
        RawJsonText: Text;
        Base64Data: Text;
        ResultText: Text;
        InfoText: Text;

    local procedure ToBase64(InputText: Text): Text
    var
        TempBlob: Codeunit "Temp Blob";
        Base64Convert: Codeunit "Base64 Convert";
        OutStr: OutStream;
        InStr: InStream;
    begin
        TempBlob.CreateOutStream(OutStr, TextEncoding::UTF8);
        OutStr.WriteText(InputText);
        TempBlob.CreateInStream(InStr, TextEncoding::UTF8);
        exit(Base64Convert.ToBase64(InStr));
    end;
}

4. Sample output

After successful execution, the result is displayed in the Response field of the page:

5. Conclusion

This plugin shows how flexibly and modularly DataMigratePro can be extended. This architecture allows new functions to be developed, tested and operated in isolated modules.

Sascha Marquardt
About the author

Sascha Marquardt

Responsible for the partner programme, the licensing business and commercial project delivery.