Azure, Azure Function Extension, Azure Functions, DotNet, Http Trigger, node.js, npm, nuget package, QR Code, QRCoder, SDK, Tip & Tricks, Visual Studio Code

Creating Azure Functions to generate QR Code

This is second post in this series, if you wish to see previous post, you can access here.

Today in this post I will discuss about first part, how to create Azure Functions.

Before we start, you need some installation to support creating Azure Functions. Use below Links to download & install these packages on the system, where you wish to write, compile & test the Azure functions.

Installation Links:

https://docs.npmjs.com/downloading-and-installing-node-js-and-npm

https://nodejs.org/en/download/

https://dotnet.microsoft.com/download/dotnet/thank-you/sdk-3.1.414-windows-x64-installer

Obviously, you must have an active Azure subscription, to create an Azure Functions App. If you don’t have, you can create an account that gives you a credit to explore Microsoft Azure for 30 days.

Head to Azure portal and sign in with your account.

Create New Function App.

Select your Azure subscription and a resource group or create a new one. Provide a name for your function app. This name will be the prefix for the URL.

You can select the .NET Core runtime and the region that matches your location. Select the Review + create button.

Now, you can create new functions. A function app can contain multiple functions. Each function will be available on:

Before you start to create Function, you need to Install dependencies:

  1. You should install Visual Studio Code
  2. You should also install Node.JS 
  3. Run the following command to install the Core Tools package:

npm install -g azure-functions-core-tools@3 –unsafe-perm true

Create an Azure Functions project

Click the Create New Project… icon in the Azure: Functions panel.

You will be prompted to choose a directory for your app. Choose an empty directory.

You will then be prompted to select a language for your project. Choose dotnet.

Create a function

If you skipped to provide details, for Functions in above process, you can still initiate later.

Click the Create Function… icon in the Azure: Functions panel.

You will be prompted to choose a template for your function. Select HTTP trigger for getting started.

Screens will be same as shown in above process.

Sample project will be created

As per the information provided by you, in above screens.

KSDQRGenerator.cs auto generated file code will be as below:

using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;

namespace Company.Function
{
    public static class KSDQRGenerator
    {
        [FunctionName("KSDQRGenerator")]
        public static async Task<IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req,
            ILogger log)
        {
            log.LogInformation("C# HTTP trigger function processed a request.");

            string name = req.Query["name"];

            string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
            dynamic data = JsonConvert.DeserializeObject(requestBody);
            name = name ?? data?.name;

            string responseMessage = string.IsNullOrEmpty(name)
                ? "This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response."
                : $"Hello, {name}. This HTTP triggered function executed successfully.";

            return new OkObjectResult(responseMessage);
        }
    }
}

Now you have the Http Template, we will make necessary changes as per our requirement.

In this example we will be using a library – QRCoder to generate the QR Code.

So first we have created a function with Http Trigger.

Made changes to the function as:

/*string name = req.Query["name"];

            string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
            dynamic data = JsonConvert.DeserializeObject(requestBody);
            name = name ?? data?.name;

            string responseMessage = string.IsNullOrEmpty(name)
                ? "This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response."
                : $"Hello, {name}. This HTTP triggered function executed successfully.";

            return new OkObjectResult(responseMessage);*/

Replace this part as below code:

            string ReqData = req.Query["ReqData"];

            string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
            dynamic data = JsonConvert.DeserializeObject(requestBody);
            ReqData = ReqData ?? data?.url;
            if (string.IsNullOrEmpty(ReqData))
            {
                return new BadRequestResult();
            }

            var generator = ReqData;
            var payload = generator.ToString();

            using (var qrGenerator = new QRCodeGenerator())
            {
                var qrCodeData = qrGenerator.CreateQrCode(payload, QRCodeGenerator.ECCLevel.Q);
                var qrCode = new PngByteQRCode(qrCodeData);
                var qrCodeAsPng = qrCode.GetGraphic(20);
                return new FileContentResult(qrCodeAsPng, "image/png");
            }

Final Code should look like this:

There are some errors, correct. Next step will resolve the same.

Next, we will add the QRCode nuget package to the dotnet core project using 

dotnet add package QRCoder –version 1.4.1

Post completing the command execution, all errors are resolved.

Run your function project locally

Press F5 to run your function app.

The runtime will output a URL for any HTTP functions, which can be copied and run in your browser’s address bar.

Copy the URL of the function & Switch to browser:

In my case: http://localhost:7071/api/KSDQRGenerator?ReqData=Test

If you scan above QRCode, you will get ‘Test’ as we have passed this as a parameter (?ReqData=Test)

To stop debugging, press Shift + F5.

Deploy your code to Azure

Click the Deploy to Function App… () icon in the Azure: Functions panel.

Sign in to your Azure Account, if not done earlier. To test locally you need not to sign in to Azure. But at deployment is must.

When prompted to select a function app, choose KSDQRCodeGenerator (in my case), Function App Created on Azure portal in the starting of this blog post.

Confirm to deployment dialog.

On completion you will get the Live AZURE URL, use the URL in same way as for local, to pass parameter append at the end of URL as (?ReqData=Test)

Replace [Test] with the information for which you want to generate the QR Code.

That’s all for this post, but visit again to learn from upcoming posts in this series, will post soon.

See you again in next post, Till then keep exploring, learning and sharing with others.

Corfu Navision 2016, Development Tips, How To, Information, Tip & Tricks, TryFunction

NAV Design Pattern: TryFunction – .NET Exception Handling in C/AL

When you want to use objects from the .NET Framework in C/AL code, one of the main challenges is to handle exceptions that the methods of these objects may throw. Eventually, if not handled, they will basically bubble up as runtime errors, halting the current operation a user is doing without having a chance to properly display errors in a user-friendly format.

For more details check following links :

https://blogs.msdn.microsoft.com/nav/2015/10/28/nav-design-pattern-tryfunction-net-exception-handling-in-cal/

You can refer my earlier post too using below link :
https://msdynamicsnavashwinitripathi.wordpress.com/2015/10/15/using-try-functions-in-navision-2016/

Corfu Navision 2016, Information

Changes in C/AL Behaviour C/AL Functions in Nav 2016

The following table lists the summary of new, removed, or changed functions in Microsoft Dynamics NAV 2016.

Will come with more details in my later posts.

Function Description
ADDFIELD Function New function.

Adds a table field to the filter control for a table on filter page.

ADDFIELDNO Function New function.

Adds a table field to the filter control for a table as specified by the field number.

ADDRECORD Function New function.

Adds a filter control for a table to a filter page as specified by a record data type variable.

ADDRECORDREF Function New function.

Adds filter control for a table to a filter page as specified by a RecordRef variable.

ADDTABLE Function New function.

Adds filter control for a table to a filter page.

BINDSUBSCRIPTION Function New function.

Binds event subscribers to the subscriber codeunit instance for handling events.

UNBINDSUBSCRIPTION New function.

Unbinds event subscribers from the subscriber codeunit instance for handling events.

COUNT Function (FilterPageBuilder) New function.

Gets the number of filter controls that are specified in the FilterPageBuilder object instance.

CREATEENCRYPTIONKEY Changed function.

Includes a Boolean return value. The value is true if an encryption key is created successfully; otherwise, it is false.

CURRENTCLIENTTYPE Function New function.

Gets the Microsoft Dynamics NAV client type that is running on the current session.

CURRENTCOMPANY Function (Record) New function.

Gets the current company of a database table record.

CURRENTCOMPANY Function (RecordRef) New function.

Gets the current company of a database table that is referred to by a RecordRef.

DEFAULTCLIENTTYPE Function New function.

Gets the default Microsoft Dynamics NAV client type that is configured for the Microsoft Dynamics NAV Server instance that is used for the current session.

GETASCENDING Function (Record) Gets the sort order for the records returned, such as in data from an ODATA web service.
GETURL Function Changed function. Includes the following changes:

  • Accepts CURRENTCLIENTTYPE and DEFAULTCLIENTTYPE as ClientType parameter.
  • Supports RecordRef variable data type as a parameter to specify the record to open.
  • Includes a Boolean parameter to include filters that are setup on the object in URL.
GETVIEW function (FilterPageBuilder) New function.

Gets the filter view (which defines the sort order, key, and filters) for the record in the specified filter control of a filter page.

IMPORTENCRYPTIONKEY Changed function.

Includes a Boolean return value. The value is true if an encryption key is imported successfully; otherwise, it is false.

ISFILTERPAGEBUILDER Function (Variant) New function.

Indicates whether a C/AL variant contains a FilterPageBuilder variable.

ISTEMPORARY Function (Record) New function.

Determines whether a record refers to a temporary table.

NAME Function (FilterPageBuilder) New function.

Gets the name of a table filter control that is included on a filter page based on an index number that is assigned to the filter control.

RECORDID (Record) New function.

Gets the RecordID of the record that is currently selected in the table.

RUNMODAL Function (FilterPageBuilder) New function.

Builds and runs the filter page.

SETASCENDING Function (Record) Sets the sort order for the records returned, such as in data from a ODATA web service.
SETVIEW Function New function.

Sets the current filter view, which defines the sort order, key, and filters, for a record in a filter control on a filter page.

GETDEFAULTTABLECONNECTION Function (Database), HASTABLECONNECTION Function (Database), REGISTERTABLECONNECTION Function (Database), SETDEFAULTTABLECONNECTION Function (Database), and UNREGISTERTABLECONNECTION Function (Database) New functions. Registers, sets, gets, and unregister table connections to external tables.
Database Functions, Development Tips

Database Function

EXPORTDATA Function (Database)

Exports data from the Microsoft Dynamics NAV database to a file. The data is not deleted from the database.

Syntax

[Ok:=] EXPORTDATA(ShowDialog, FileName[, IncludeApplicationData][, IncludeGlobalData][, CompanyRecord])

Parameters

ShowDialog

Type: Boolean

Specifies if you want to display a dialog box where the user can confirm the action.

FileName

Type: Text

Specifies the name and location of the file that the data must be exported to. The file must have the .navdata extension.

IncludeApplication

Type: Variable

Specifies if you want to export the application objects.

Create a variable of type Boolean to specify this parameter.

IncludeApplicationData

Type: Variable

Specifies if you want to export the data that defines the application in the database. This includes the permissions, permission sets, profiles, and style sheets.

Create a variable of type Boolean to specify this parameter.

IncludeGlobalData

Type: Variable

Specifies if you want to export global, non-company specific data.

Create a variable of type Boolean to specify this parameter.

CompanyRecord

Type: Record

Specifies the company or companies that must be imported.

You can find the usage of this function in Std. Page Object 9901 [Export Data]
DatabaseFunction-1

IMPORTDATA Function (Database)

Imports data from a file that has been exported from a Microsoft Dynamics NAV database.

Syntax

[Ok:=] IMPORTDATA(ShowDialog, FileName[, IncludeApplicationData][, IncludeGlobalData][, CompanyRecord])

Parameters

ShowDialog

Type: Boolean

Specifies if you want to display a dialog box where the user can confirm the action.

FileName

Type: Text

Specifies the name and location of the file that must be imported. The file must have been exported from a Microsoft Dynamics NAV database.

IncludeApplicationData

Type: Variable

Specifies if you want to import the data that defines the application in the database. This includes the permissions, permission sets, profiles, and style sheets.

Create a variable of type Boolean to specify this parameter.

IncludeGlobalData

Type: Variable

Specifies if you want to import global, non-company specific data.

Create a variable of type Boolean to specify this parameter.

CompanyRecord

Type: Record

Specifies the company or companies that must be imported.

You can find the usage of this function in Std. Page Object 9900 [Import Data]
DatabaseFunction-2

DATAFILEINFORMATION Function (Database)

Specifies data from a file that has been exported from a Microsoft Dynamics NAV database.

Syntax

[Ok:=] DATAFILEINFORMATION(ShowDialog, FileName, Description, HasApplication, HasApplicationData, HasGlobalData, tenantId, exportDate, CompanyRecord)

Parameters

ShowDialog

Type: Boolean

Specifies if you want to display a dialog box where the user can confirm the action.

FileName

Type: Text

Specifies the name and location of the file that you want to read information from. The file must have been exported from a Microsoft Dynamics NAV database.

HasApplication

Type: Variable

Specifies if the file contains application objects.

Create a variable of type Boolean to specify this parameter.

HasApplicationData

Type: Variable

Specifies if the file contains the data that defines the application in the database. This includes the permissions, permission sets, profiles, and style sheets.

Create a variable of type Boolean to specify this parameter.

HasGlobalData

Type: Variable

Specifies if the file contains global, non-company specific data.

Create a variable of type Boolean to specify this parameter.

tenantId

Type: Variable

Specifies the tenant ID of the database that the data was exported from.

Create a variable of type Text to specify this parameter.

exportDate

Type: Variable

Specifies the date and time when the data was exported.

Create a variable of type DateTime to specify this parameter.

CompanyRecord

Type: Record

Specifies the company or companies in the file.

You can find the usage of this function in Std. Page Object 9900 [Import Data]
DatabaseFunction-3