09 October 2019

Directions EMEA 2019 : We safely landed in Vienna

We safely landed in Vienna after flying over more than 18000+ Km. This is just normal to most of us who live on the edge of the world. As our prime minister used says even the shortest flight to our neighbor is more than 4 hours away. So flying for more than 24 hours is quite common for most of us.  
Sometimes it feels New Zealand is far away from the rest of the world, but that is the same feeling that holds us tight to the beautiful island nation. This is my first time in Vienna and also to Directions EMEA. Wagner and I presented in the last two Directions ASIA conferences but I’m sure the vibe is totally different in Directions EMEA. 

We will be conducting 3 sessions and all our sessions are focused on integrating Microsoft Dynamics 365 Business Central with the outer world with the help of Azure integration Services. We are planning to take the audience through some of the very interesting Azure technologies that are built to make the integration life easy. 

If you are planning or already working with integration scenarios you might want to book your slot with us. 

Sessions :
“Logic Apps x Microsoft Flow, which one should I choose?" | Date: Wednesday, October 9, 2019 | From: 15:30:00 to 16:15:00 | Room: HALLG1

Unlocking new integration potential for Dynamics 365 BC with Azure Event Grid and Azure Integration | Date: Thursday, October 10, 2019 | From: 11:00:00 to 11:45:00 | Room: HALLG2

Exploring Azure Integration Services - Extending D365 BC with the power of integration | Date: Thursday, October 10, 2019 | From: 16:00:00 to 16:45:00 | Room: HALLG1

Theta: 
This year we got 4 people attending Directions EMEA representing THETA (NZ). Joerg Rau (Head of Theta ERP) is a frequent attendee to Directions EMEA and together with him Carl Head, Wagner Silveira and myself are planning to attend almost all the possible sessions we can, to grasp the latest technologies related to Microsoft Dynamics 365 Business Central. 

The knowledge we gather during the Directions EMEA helps us to add more value and flavor to the solutions we deliver to our customers back home. Even though we are far away from the rest of the world, this keeps us toe to toe with all the other partners in Europe and the US. 

If you see us during the conference(I’m sure you will) don’t be a stranger and just say hi. I would love to get to know you all and who knows the possibilities that might open with just a small “hi”. 

See you tomorrow!
Read more »

14 July 2019

Too many requests reached

What is the maximum number of API requests Microsoft Dynamics 365 Business Central can handle within a one minute? 

Ran into this question a couple of months ago, specifically soon after the April release. Most of our Azure Logic Apps integrations to Microsoft Dynamics 365 Business Central started to fail due to API endpoint changes

Logic Apps were kept on failing every time it tries to push the data into the MSDYN365BC. Initially, the error was related to URI.


1
2
3
4
5
6
{
    "error": {
        "code": "BadRequest_NotFound",
        "message": "The request URI is not valid. Since the segment 'customers' refers to a collection, this must be the last segment in the request URI or it must be followed by an function or action that can be bound to it otherwise all intermediate segments must refer to a single resource."
    }
}

After a while error message changed into "Too many requests reached".

1
2
3
4
5
6
7
{
  "error": {
    "code": "Application_TooManyRequests",
    "message": "Too many requests reached.  Actual (101).  Maximum (100)."

  }
}

So there is a limit! What is the limit and why there is a limit? To get an answer to all these questions we request support from Microsoft. While we wait for an answer from Microsoft we found the answer to our questions from Microsoft Docks: Business Central (Preview)

The document is related to the Business Central Connector and it specifically mentioned that Microsoft Dynamics 365 Business Central can ONLY handle 100 API calls per minute




The limit is enforced mainly to avoid DoS attacks (denial-of-service attack) and to make sure Microsoft Business Central runs smoothly. Too many API requests can bring the product to its knees causing a probable outage.

I suggest you read the "API Limits" article by Microsoft If you are working on the D365 integrations. Even though the article does not directly talk about BC, all the rules discuss it does apply to the BC as well.

Please provide your feedback with a comment. 
Thank you and Regards,
Tharanga Chandrasekara
Read more »

PowerShell: Run Script Error: Exception setting "CursorPosition"

Last week I was working on a PS script to upload files to an FTP and this script supposes to runs through a windows service. It runs perfectly well when it runs manually with the PowerShell ISE.

However, when I scheduled it to run it through a service, service logs below error in the error log. 
Run Script Error: Exception setting "CursorPosition": "A command that prompts the user failed because the host program or the command type does not support user interaction. Try a host program that supports user interaction, such as the Windows PowerShell Console or Windows PowerShell ISE, and remove prompt-related commands from command types that do not support user interaction, such as Windows PowerShell workflows."
While creating the script, I did add CLS to the script to clear the screen, so I can see the execution steps in the output window very clearly. This simple command was causing the error when it runs through the service. Only thing I had to do was simply remove the CLS and restart the service. 

Please provide your feedback with a comment. 
Thank you and Regards,
Tharanga Chandrasekara
Read more »

13 July 2019

How to inject data to Customer Address Line 2 using Microsoft Business Central API

Creating a customer record in Microsoft Dynamics 365 Business Central is a topic I blogged about in one of my previous blog posts. If you have not read them yet I suggest you read it before going through this for better understanding. 

Part 01: Getting Started with Dynamics 365 Business Central APIs
Part 02: Understanding Microsoft Business Central Out-Of-The-Box API Endpoints
Part 03: Understanding Microsoft Business Central Custom API Endpoints

If you want to insert below address to Business Central Customer Card then how would your JSON body look like?


Field Name in BC
Data to inject
Address
 2/34
Address 2
 Coliseum Drive
City
 Albany
County
 Auckland
Country
 NZ
Postal Code
 0632 

First Attempt:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
{
 "number": "CUST0012",
 "displayName": "Tailspin Toys",
 "type": "Company",
 "email": "jordan.moresby@contoso.com",
 "currencyCode": "NZD",
 "address": {
     "street": "2/34, Coliseum Drive ",
     "city": "Albany",
     "state": "Auckland",
     "countryLetterCode": "NZ",
     "postalCode": "0632"
 }
}

Outcome :

As you can see the first attempt did not work as expected. Address and Address 2 both end up in one field.

Second Attempt :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
{
 "number": "CUST0012",
 "displayName": "Tailspin Toys",
 "type": "Company",
 "email": "jordan.moresby@contoso.com",
 "currencyCode": "NZD",
 "address": {
     "street": "2/34, \r\nColiseum Drive ",
     "city": "Albany",
     "state": "Auckland",
     "countryLetterCode": "NZ",
     "postalCode": "0632"
 }
}

Outcome:
It did work and the "Address 2" field gets filled with the data we wanted. The change I did was I added \r\n into my JSON body. \r\n is used as a newline character in Windows and this is a very common way to go to a new line. 

 \r\n = CR + LF → Used as a new line character in Windows  

Please provide your feedback with a comment. 
Thank you and Regards,
Tharanga Chandrasekara
Read more »

Understanding Microsoft Business Central Custom API Endpoints

This is the third blog post about the Microsoft Business Central APIs and I suggest you go through below blog posts first if you haven't read them yet.

Part 01: Getting Started with Dynamics 365 Business Central APIs
Part 02: Understanding Microsoft Business Central Out-Of-The-Box API Endpoints

If you want to access custom developed API then this blog post will give you the details of how the API endpoint will be. 

** from this point onwards "https://api.businesscentral.dynamics.com" will be referred to as "{BaseURL}

Tenant version is below 14.1:

{BaseURL}/v1.0/<your tenant domain>/<environment name>/api/<api publisher>/<api group>/<api version>

Tenant version is 14.1 or above:

{BaseURL}/v2.0/<your tenant domain>/<environment name>/api/<api publisher>/<api group>/<api version>

You might be wondering from where the "api publisher", "api group" and "api version" are coming from. These values are defined during the development of the custom API.

Below is a custom developed API page and these values are defined as properties of the page.

Below are the endpoints to access above mentioned custom API.
Tenant version is below 14.1:

{BaseURL}/v1.0/<your tenant domain>/<environment name>/api/tc/iot/beta/companies/<companyID>/outdoortempentries

Tenant version is 14.1 or above:


{BaseURL}/v2.0/<your tenant domain>/<environment name>/api/tc/iot/beta/companies(<companyID>)/outdoortempentries

Please provide your feedback with a comment. 
Thank you and Regards,
Tharanga Chandrasekara
Read more »

Understanding Microsoft Business Central Out-Of-The-Box API Endpoints

If you are working on a project which involves integrating a third party application to Microsoft Dynamics 365 Business Central, then I assume you have already come across with the Business Central APIs. 

I noticed that most of the developers are still not comfortable with the endpoints of the BC APIs. Therefore this blog post is about how to understand the BC API endpoints.

Endpoint contains a couple of sections.

Sections of the URL
Purpose
https://api.businesscentral.dynamics.com
Base URL. This will be the same for all the out-of-the-box APIs and for custom APIs
/v1.0
Version
/your tenant domain
Domain name or ID
/environment name
Environment name. Can get the name from the admin portal. Ex: production, sandbox
/api
This is a keyword
/beta 
The version of the API.

** from this point onwards "https://api.businesscentral.dynamics.com" will be referred to as "{BaseURL}

If you want to use out-of-the-box API then the endpoint would be : 
{BaseURL}/v1.0/<your tenant domain>/<environment name>/api/beta  

Might get an error like below when calling the endpoint even though the correct credentials were provided with the request. 

1
2
3
4
5
6
{
    "error": {
        "code": "Authentication_InvalidCredentials",
        "message": "The server has rejected the client credentials."
    }
}

I encountered this recently and manage to find the reason behind this. Above endpoint will only work if your tenant version is below 14.1. If the tenant version is 14.1 or above then it is a must to use the API version 2.0. (yet to confirm by the Microsoft)

For the tenant which are 14.1 or above endpoint would be:


{BaseURL}/v2.0/<your tenant domain>/<environment name>/api/beta   

Result body will contain all the out-of-the-box APIs for Business Central.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
{
    "value": [
        {
            "name": "items",
            "kind": "EntitySet",
            "url": "items"
        },
        {
            "name": "companies",
            "kind": "EntitySet",
            "url": "companies"
        },
        {
            "name": "customers",
            "kind": "EntitySet",
            "url": "customers"
        }
    ]
}

Before you call any other API it is a must to point the URL to a specific company. In order to do that you can call the below Endpoint
Tenant version is below 14.1:

{BaseURL}/v1.0/<your tenant domain>/<environment name>/api/beta/companies

Tenant version is 14.1 or above:


{BaseURL}/v2.0/<your tenant domain>/<environment name>/api/beta/companies

It will return all the companies available in the tenant. 

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
{
    "value": [
        {
            "id": "e3dbe661-9c12-47d0-81f8-1186bd32518ab",
            "systemVersion": "34093",
            "name": "CRONUS NZ",
            "displayName": "CRONUS NZ",
            "businessProfileId": ""
        },
        {
            "id": "e15523c2-b04f-438c-b1bc-756321a91fae",
            "systemVersion": "34093",
            "name": "My Company",
            "displayName": "My Company",
            "businessProfileId": ""
        }
    ]
}

Version 14.1 and above treat segments as collections. Therefore it is a must to use ( ) when specifying a single record in all the new tenant versions. 

Tenant version is below 14.1:

{BaseURL}/v1.0/<your tenant domain>/<environment name>/api/beta/companies/<companyID>

Tenant version is 14.1 or above:

{BaseURL}/v2.0/<your tenant domain>/<environment name>/api/beta/companies(<companyID>)

Once you select the company, you can call the other entities in the same way you call the companies. 

As an example below calls will give you the list of items available. 
Tenant version is below 14.1:
{BaseURL}/v1.0/<your tenant domain>/<environment name>/api/beta/companies/<companyID>/items

Tenant version is 14.1 or above:

{BaseURL}/v2.0/<your tenant domain>/<environment name>/api/beta/companies(<companyID>)/items

If you want to retrieve a single item then below can be used
Tenant version is below 14.1:
{BaseURL}/v1.0/<your tenant domain>/<environment name>/api/beta/companies/<companyID>/items/<itemID>

Tenant version is 14.1 or above:

{BaseURL}/v2.0/<your tenant domain>/<environment name>/api/beta/companies(<companyID>)/items(<itemID)

Good luck and happy integration!

Please provide your feedback with a comment. 
Thank you and Regards,
Tharanga Chandrasekara
Read more »

01 July 2019

Fourth consecutive year as a Microsoft Most Valuable Professional (MVP) - Business Applications

Honored to receive my 4th consecutive MVP award for Business Applications. 

Congratulations to my fellow MVPs and best wishes to those boarding on a new journey. A special shout-out goes to my family, @ThetaNet, @MSDYN365BC, and @freddydk for all the support!


Thank you, everyone, for helping me out on this great journey and planning to do more in this year. 

Thank you and Regards,
Tharanga Chandrasekara
Read more »

05 March 2019

Dynamics 365 Business Central: Permissions required to download AL symbols

Your user needs to have the necessary permission to download AL symbols from Visual Studio Code (VSCode), else you will end up with "Could not download symbols" error in VS Code.

In order to download symbols, User needs to have SUPER permission or should have "D365 EXTENSION MGT" permission assigned. Symbols are stored per tenant and not per company, therefore Company field must be blank in either option.

Clear credentials cache in VSCode and sign in again from VS Code (Download symbols and it will ask your credentials to sign in) 
once you have the "D365 EXTENSION MGT" permission group or SUPER permission set assigned to the user, 
This time VSCode will successfully download symbols from Microsoft Dynamics 365 Business Central.


Please provide your feedback with a comment.
Thank you and Regards,
Tharanga Chandrasekara
Read more »

01 March 2019

How to check Microsoft Dynamics 365 Business Central tenant version

You can use the "System Information" page to check the current version of Microsoft Dynamics 365 Business Central tenant.

Simply search for "System Information" using "Tell me what to do" and click on the "System Information" link in the result. 

"System information" page will show the current version of the tenant. Version get change every time Microsoft upgrade the tenant.

Another way of checking the platform version is by using the admin center. 

Please provide your feedback with a comment. 
Thank you and Regards,
Tharanga Chandrasekara
Read more »

How to access action output in Logic Apps

If you are working on Logic App to integrate Microsoft Dynamics 365 Business Central with any other third party application, by now most probably you must have used HTTP requests or custom connectors (mainly with SOAP web services). 

I saw a couple questions in the forum asking how to access action output in Logic App. 

Below JSON is copied from an action output:
 {  
  "Soap:Envelope": {  
   "@xmlns:Soap": "http://schemas.xmlsoap.org/soap/envelope/",  
   "Soap:Body": {  
    "isPostingPeriodOpen_Result": {  
     "@xmlns": "urn:microsoft-dynamics-schemas/codeunit/GenJnlPost",  
     "return_value": "false"  
    }  
   }  
  }  
 }  

What if you want to read the "return_value" field of the action output? You can use any of the below statements based on your requirement. 
  • Below statement will return the actual value or if the value is empty it will return ''
 {ActionOutputs('Compose_isPostingAllowed')?['Soap:Envelope']?['Soap:Body']?['isPostingPeriodOpen_Result']?['return_value']}   
  • Below statement will return the actual value or if the value is empty it will return null
 ActionOutputs('Compose_isPostingAllowed')['Soap:Envelope']['Soap:Body']['isPostingPeriodOpen_Result']['return_value']  

Please provide your feedback with a comment. 
Thank you and Regards,
Tharanga Chandrasekara
Read more »

28 February 2019

Call a Microsoft Dynamics 365 Business Central function through a Web Service : SOAPAction

Today I did some work with a Logic Apps and one of the requirement was to call a Business Central function through a Web Service. 

I normally use Postman to simulate requests, export the collection and use that to create the Logic App connector. 

Codeunit which I published as a web service had few functions exposed. I wanted to call one of those functions with values passing in and read the return value. 

If I just call (POST) Web Service with the SOAP Envelope (Like below image) it will just return the WDSL. Not the result I was expecting. 

Header :

SOAP Request and Response:

However, SOAP UI return the value I was expecting it to return. 

How that can be possible?  We looked into the "HTTP log" of the SOAP UI, and we saw SOAPAction is defined and its pointing to the function I want to call. 


I did the same thing in Postman and it worked. Below is my request header and you can notice that I add "SOAPAction" to the header. 
If you didn't define the "SOAPAction" in the request header, the result will bring back the WDSL regardless of your SOAP Envelope. 
I use the postman request to create my HTTP request in Logic App. There is a much easy way of doing this in Logic App with the help of custom connector. I will share those details in another day from a new blog post. 

** Thank you Stephen Gichure for helping me to prepare this blog post.

Please provide your feedback with a comment. 
Thank you and Regards,
Tharanga Chandrasekara
Read more »

21 February 2019

Add a logo to a Microsoft Dynamics 365 Business Central Extension


I saw a couple of forum questions about how to add a logo to an AL Extension and I thought to share a quick guide on how to. 

If you publish your new extension to Microsoft Dynamics 365 Business Central and then navigate to Extension management page, you will see your new extension as below (My extension is "Demo Extension"). 

You only need to follow a couple of simple steps to add a logo to your new extension.
1. Place the image into your Repo.
2. Refer to the image from app.json file


You can simply copy the image to any folder that you have within your workplace. I always prefer to keep things organize so I know where my .al files and other extension related files are. Therefore I will copy the logo to my res (resource) folder where I keep all my resources related to the current extension. 
Once the above step is complete, you can open the app.json file and set the logo setting to refer to the logo you just copied. Please refer below screenshot :

You might have noticed that my file path starting with ".", it means the current working folder or in my case the Repo.
Once you have the "logo" setting set in the app.json file you can simply compile and deploy the extension to Microsoft Dynamics 365 Business Central. This time it will get published with the logo.  

Please provide your feedback with a comment. 
Thank you and Regards,
Tharanga Chandrasekara
Read more »

19 February 2019

Runtime Packages for Business Central On-Premises


Before you go through this blob, I suggest you read my blog post "Your program license does not allow you to publish" to get an understanding about the Runtime Packages. 

Runtime packages are designed to help the distribution of extensions. You can generate Runtime packages that do not contain AL code. Runtime packages allow protecting the AL source code. 


The biggest advantage to me is that extension in a runtime package can be installed on a server that does not have a developer license. In other words, you can install the runtime extension to the production without changing the customer license to a developer license. 

The license is only checked on the server where the runtime package is generated. 

How to get the runtime packages:
It is a must to install the extension into an on-premise instance to export the runtime package. next step is to connect to the instance through PowerShell and then download the runtime package. 

You can use "Get-NavAppRuntimePackage" PowerShell cmdlets do download the extension:


 Get-NAVAppRuntimePackage -ServerInstance DynamicsNAV -AppName 'Proseware SmartApp' -Version 2.3.4.500 -ExtensionPath 'Prosware SmartApp_2.3.4.500_runtime.app'   
Once you have the runtime extension you can use the Publish-NavApp and the Install-NAVApp PowerShell cmdlets to publish and install the extension. 


Limitations
Runtime package only works for on-premise installations and cannot be used with AppSource. Addition to that  debugging experience is very limited since the no source code is available 

Please provide your feedback with a comment. 
Thank you and Regards,
Tharanga Chandrasekara
Read more »

Your program license does not allow you to publish


We recently ran into a new issue when we try to push one of our extensions to Microsoft Dynamics NAV 2018 On-premise installations. 

We used PowerShell script to upload the extensions to production and we did this couple of days ago too without an issue. However this time we got the below error during the installation :

"Your program license does not allow you to publish <table extension name>"


The instance was running with the customer's license and we realized we need to find an alternative method. We had a couple of options, 
1. Change the license, upload the extension and then change the license back
2. Create a new instance and use a development license to upload the extension
3. Try the runtime app option


We first went with the option 01 but we end up with the same error. Even though we upload the license to the instance we could not restart the service, therefore, we were unable to bypass the license issue. 


We went with the third option this time to see how it's going to work. If you like to read more about it please use this link.

We install the extension to the Development environment which was running with the Developer license and then used below PowerShell command to export the Runtime Package. 


 Get-NAVAppRuntimePackage -ServerInstance DynamicsNAV -AppName 'Proseware SmartApp' -Version 2.3.4.500 -ExtensionPath 'Prosware SmartApp_2.3.4.500_runtime.app'  


Once we got the Runtime package we install it to the production environment with the use of the Publish-NavApp and the Install-NAVApp PowerShell cmdlets. 

Runtime package installations skip the license check so you can use this option to install extensions to a Production environment without changing the license. 

** Thank you Isa Sen for helping me to prepare this blog post.

Please provide your feedback with a comment. 
Thank you and Regards,
Tharanga Chandrasekara
Read more »

Function Overloading in AL with Option and Integer


We never had the luxury of overloading a function in C/AL, but with the AL we have that ability. Which means you can use the same function name with different parameters. 

This blog post is about a small glitch in the function overloading in AL and I will write a separate blog post about function overloading and its implementations (Excited about it). 


I had below function signatures in my code and each of these functions is called from 6 different places. 
 procedure InsertData(Code: code[10]; lDelimiter: Option Comma,Tab,SemiColon,"Fixed")  

 procedure InsertData(Code: code[10]; configType: Integer; Config: Boolean)  

However, I noticed that the second function got 12 references from the function calls and the first one got none (should be 6 each).  




Reason for the 
glitch: Option is also passed as an integer to the function so compiler sees both the function signatures as same. 


What I assume is, even though the AL compiler does not give an error during compiling of the code it still sees both the function signatures as the same. That is why it is referencing all the function calls to one function.

** In order to replicate this, function signature needs to have the same number of parameters.

** Thank you Stephen Gichure for helping me to prepare this blog post.

Please provide your feedback with a comment. 
Thank you and Regards,
Tharanga Chandrasekara
Read more »