Thursday, May 7, 2020

QR Codes in Ax 2012 and C#

I had a request over the last couple of days to add  a QR Code to 2 SSRS reports: 1 in Ax 2012 and another in a WPF application written in C#.  QR Codes are of often thought as a font and they are somewhat analogous.  However, it was very clear very early that QR Codes are images.

In X++, QR codes can be created in a container.  The container can be an field on a table.  Once it's populated, you place it on your SSRS report and it displays.  It is very similar with D365.  To keep things easy, I wrote the QR Code Generation into a static method in a class.

server static container createQRCode(Str1260 qrString)
{
    Microsoft.Dynamics.QRCode.Encoder   qrCode;
    System.String                       netString;
    str                                 tempFileName;
    System.Drawing.Bitmap               netBitmap;
    FileIOPermission                    perm;
    BinData                             binData;
    container                           result;
    ;

    netString = qrString;
    qrCode = new Microsoft.Dynamics.QRCode.Encoder();
    qrCode.set_Version(10);
    netBitmap = qrCode.Encode(netString); //encode the string as Bitmap can be used already

    tempFileName = qrCode.GetTempFile(netString); //to get the QR temporary file

    perm = new FileIOPermission(tempFileName,'r');
    perm.assert();
    binData = new binData();
    binData.loadFile(tempFileName);
 //get the QR code image put inside container so can be stored inside database for storing or reporting purpose
    result = binData.getData();
    System.IO.File::Delete(tempFileName);

    CodeAccessPermission::revertAssert();

    return result;
}

In the WPF application, I decided to install a 3rd party component: MessagingToolkit.QRCode.  I found it on NuGet at https://www.nuget.org/packages/MessagingToolkit.QRCode.  Although it is a bit old, it worked perfectly.  The only trick is that SSRS does not recognize Image objects coming from .Net, rather its image widget needs to be populated with a Byte array.  However, once that hurdle is figured out, the rest was rather easy.

using MessagingToolkit.QRCode.Codec;
...

public Byte[] QRCode
        {
            get
            {
                QRCodeEncoder encoder = new QRCodeEncoder();
                encoder.QRCodeVersion = 10; //higher versions allow larger QR Codes.
                encoder.QRCodeErrorCorrect = QRCodeEncoder.ERROR_CORRECTION.M;

                string qrText = this._ticket.Number + ", " + this._ticket.NetWeight.ToString();
                Bitmap qrCode = encoder.Encode(qrText, new UTF8Encoding());
                MemoryStream imageStream = new System.IO.MemoryStream();
                qrCode.Save(imageStream, System.Drawing.Imaging.ImageFormat.Png);

                return imageStream.GetBuffer();
            }
        }

One thing to notice: the MS component, save the QR Code to a temp file and then loads it into byte array (BinData).  The MessagingToolkit is nicer as the operation appears to be done entirely in memory.

No comments:

Post a Comment