Pages

1/29/2022

Easy way to make chat bot on Business Central with Power Virtual Agent

I will show how to fast and easy create chat bot on Business Central. 

For this solution we need : 
  • Power Virtual Agents - (https://powervirtualagents.microsoft.com/en-us/ there is free subscription for 60 day, Later it cost from 450$ till 1000$) 
So when you have subscription  then you need to create chat bot:

Let's name it "BC Virtual Consultant
":

When we created chatbot we can manage topic on what chatbot will give answers.
Let's create topic on "Sales document":


Create answer's.  Click on "Go to authoring canvas"
There you can create your answers

When our chat bot topics already created then we can publish chat bot. 
Go to the publish area.



Click on Publish button

Then click on "Go to Channel" and select "Custom website"

Copy html code snippet. We will need it later.

Now we can go to create Busness Cenrall extension for that chat bot.

Create new page in BC extension project:

page 50001 "Chat Bot Card"
{
    PageType = Card;
    ApplicationArea = All;
    UsageCategory = Administration;

    layout
    {
        area(Content)
        {
            usercontrol(ControlName; "Microsoft.Dynamics.Nav.Client.WebPageViewer")
            {

                ApplicationArea = All;
                trigger ControlAddInReady(callbackUrl: Text)
                begin
                    CurrPage.ControlName.SetContent('<!DOCTYPE html><html><body>
<iframe src=" Copy your own link"
frameborder="0" style="width: 100%; height: 100%;"></iframe>
</body></html>');
                end;

                trigger Callback(data: Text)
                begin
                    CurrPage.Close();
                end;

            }
        }
    }

}



Run project and let's try our chat bot :)

We get answer on topic

















10/24/2020

Barcodes & QRCodes in Dynamics 365 Business Central Using Azure App Functions

There is simple way how to create barcode generator for Dynamics 365 Business Central using Azure app functions.

First what we need it is 

  • Azure account with subscription, 
  • Visual Studio and 
  • Visual Studio code  
  • In my case Docker with BC container

In order to create our azure function lets head to: portal.azure.com

Press on Functions App


Then Add  Function App


In finish of this step we should have Function App in list:


Next step will be with Visual Studio create function witch will be generate barcode image.

So lets open Visual studio (Visual Studio 2019)  and create new project :

In Visual Studio, select New > Project from the File menu.

In the New Project dialog, select Installed, expand Visual C# > Cloud, select Azure Functions, type a Name for your project, and click OK. The function app name must be valid as a C# namespace, so don't use underscores, hyphens, or any other nonalphanumeric characters.


Write name and press create


 Select Http Trigger (Function will be activated by REST request)

Autentication level you can choose some option. In my case i will choose Function


In our Visual Studio project  should instal this two NuGet Package:

Change file ant class name to "GetBarcode": 

and fix code in class:

Change the code to generate barcode  (GetBarcode.cs):

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;
using System.Drawing.Imaging;
using ZXing;
using ZXing.Common;
using System.Drawing;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Collections.Generic;

namespace CreateBarcode
{
    public static class GetBarcode
    {
        [FunctionName("GetBarcode")]
        public static async Task<HttpResponseMessage> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
            ILogger log)
        {
            string requestBody = await new StreamReader(req.Body).ReadToEndAsync();            
            Dictionary<string, string> reqField = JsonConvert.DeserializeObject<Dictionary<string, string>>(requestBody);
            var writer = new BarcodeWriter();
            writer.Format = BarcodeFormat.CODE_128;

            switch (reqField["Type"])
            {
                case "CODE_39":
                    writer.Format = BarcodeFormat.CODE_39;
                    break;
                case "CODE_128":
                    writer.Format = BarcodeFormat.CODE_128;
                    break;
                case "QR_CODE":
                    writer.Format = BarcodeFormat.QR_CODE;
                    break;
                case "PDF_417":
                    writer.Format = BarcodeFormat.PDF_417;
                    break;
                case "UPC_A":
                    writer.Format = BarcodeFormat.UPC_A;
                    break;
                case "EAN_13":
                    writer.Format = BarcodeFormat.EAN_13;
                    break;
                case "CODE_93":
                    writer.Format = BarcodeFormat.CODE_93;
                    break;
                case "DATA_MATRIX":
                    writer.Format = BarcodeFormat.DATA_MATRIX;
                    break;
                case "MAXICODE":
                    writer.Format = BarcodeFormat.MAXICODE;
                    break;
                case "EAN_8":
                    writer.Format = BarcodeFormat.EAN_8;
                    break;
                case "PHARMA_CODE":
                    writer.Format = BarcodeFormat.PHARMA_CODE;
                    break;
                default:
                    var response = new HttpResponseMessage()
                    {
                        Content = new StringContent("Error: (1) Barcode Type can be only:CODE_39; CODE_128; QR_CODE; PDF_417; UPC_A; EAN_13; CODE_93; DATA_MATRIX; MAXICODE; EAN_8; PHARMA_CODE; "),
                        StatusCode = HttpStatusCode.BadRequest
                    };
                    return response;
            }

            writer.Options = new EncodingOptions
            {
                Height = System.Convert.ToInt32(reqField["Height"]),
                Width = System.Convert.ToInt32(reqField["Width"])
            };

            var barcodeBitmap = writer.Write(reqField["Value"]);

            var barcodeImg = (Image)barcodeBitmap;
            using (var memStream = new MemoryStream())
            {
                barcodeImg.Save(memStream, ImageFormat.Png);
                var response = new HttpResponseMessage()
                {
                    Content = new ByteArrayContent(memStream.ToArray()),
                    StatusCode = HttpStatusCode.OK,
                };
                response.Content.Headers.ContentType = new MediaTypeHeaderValue("image/png");
                return response;
            }
        }
    }
}

Before publish to azure you can test it locally, by passing rest request to adress showing in console window.
 

 

 Now lets try our function project publish to Azure. Go Build>Publish CreateBarcode. Select Azure and then Azure function App (Windows)

 




Finish publishing. On next screen finish cofigure because mostly time it have warning message:


Do not forget mark NuGet packages on configure.


Now we can finish publishing by pressing Publish button

 

After publishing return to Azure portal ant take Function App adress:


https://testforbarcode.azurewebsites.net/api/GetBarcode?code=VUNTbrqdEBMZhuArrjsZ29MKuY4T2YRqebXvvv2XXEgeuavyz7Hg7w==

So now we can create RDLC report on Business Central. 

Rep50100.ItemBarcode.al

 

report 50100 "Item Barcode"
{
    DefaultLayout = RDLC;
    RDLCLayout = './R50100.rdl';

    dataset
    {
        dataitem(Item; Item)
        {
            column(Barcode; TmpTempBlob.Blob) { }
            column(No; Item."No.") { }
            column(Description; Item.Description) { }

            trigger OnAfterGetRecord()
            begin
                GetBarcode(TmpTempBlob, Item."No.");
            end;
        }
    }
    requestpage
    {
        layout
        {
            area(content)
            {
                group(GroupName)
                {
                }
            }
        }
        actions
        {
            area(processing)
            {
            }
        }
    }
    var
        TmpTempBlob: Record TempBlob temporary;

    procedure GetBarcode(var BarcodeImg: Record TempBlob; Value: Text)
    var
        Client: HttpClient;
        RequestMessage: HttpRequestMessage;
        RequestContent: HttpContent;
        ResponseMessage: HttpResponseMessage;
        InStr: InStream;
        OutStr: OutStream;
    begin
        BarcodeImg.RESET;
        BarcodeImg.DeleteAll();

        RequestMessage.Content.WriteFrom(StrSubstNo('{"Type": "%1","Height": "%2","Width": "%3","Value": "%4" }', 'CODE_128', '50', '200', Value));
        Client.DefaultRequestHeaders.Add('x-functions-key', 'VUNTbrqdEBMZhuArrjsZ29MKuY4T2YRqebXvvv2XXEgeuavyz7Hg7w==');
        Client.Post('https://testforbarcode.azurewebsites.net/api/GetBarcode', RequestMessage.Content, ResponseMessage);


        BarcodeImg.Init;
        BarcodeImg.Blob.CreateInStream(InStr);
        ResponseMessage.Content.ReadAs(InStr);
        BarcodeImg.Blob.CreateOutStream(OutStr);
        CopyStream(OutStr, InStr);
        BarcodeImg.Insert();
        BarcodeImg.CALCFIELDS(Blob);

    end;
}

Add to rdlc image and setup this parameter:



Run report and we have a result :)


 If you run BC from Docker container be sure that in docker DNS settings are set