Visibility:
September 12, 2023
September 05, 2023
Encrypted field in D365 FO
Creating an encrypted field in Dynamics 365 Finance and Operations is a simple process that can help secure sensitive information in your application. By using an encryption key to encrypt the data, it ensures that the data remains safe even if it is accessed by unauthorized users.
By encrypted field I mean what you see, for example, in the Email parameters form for the SMTP password:
These encrypted fields aren’t stored as plain text in the database, instead they’re encrypted (as its name suggests) using a key and that value is saved.
It’s worth mentioning that each environment has a different encryption key, so when you refresh a sandbox or development environment with data from another environment, the values of encrypted fields are lost because they can’t be unencrypted with a different key.
Creating it
You need a new field in a form, you know that the first step is creating it in a table. For this example, I’ll be adding a field to the CustParameters table and form.
So extend the table in your model and go to the EDTs in the AOT and drag and drop the EncryptedField EDT into the CustParameters table extension. Give it the name you want, I’ll name mine TestEncryptedField, and let’s continue.
Next, you need to create a code extension for the CustParameters table. Because encrypted fields are shown on forms as an edit field, we need a method to encrypt and decrypt the content of the field, and that’s what we’ll do here:
[ExtensionOf(tableStr(CustParameters))]final class CustParameters_Test_Extension{ public edit Name TestEncryptedNameEdit(boolean _set, Name _value) { return Global::editEncryptedField(this, _value, fieldNum(CustParameters, TestEncryptedField), _set); }}This is a regular edit method, but it’s calling Global’s editEncryptedField method and there it’s calling Appl’s class EncryptForPurpose and DecryptForPurpose kernel methods that do the job.
Defining an EDT as the return type in the method will help us display the right label in the form, so create your EDTs or use one that fits your purpose. I’m using the Name one because this is just a demo!
Finally, we’ll add a string field in the form and set the CustParameters table as its Data Source property, and the CustParameters_Test_Extension.TestEncryptedNameEdit method as its Data Method property. If your field’s base data type is not a string, you need to add the correct type of new field!
Synchronize, compile and let’s take a look at the field in the UI:
You need to set the form field’s property Password style to Yes! Otherwise, it’ll only show plain text. Let me change that…
August 22, 2023
Disable export to Excel on forms - D365 FO
We can disable the export to Excel option in list pages, there is an option on grid properties “Export to Excel”. By default, it is true. By changing it to false we can disable export to excel on specific form.
August 18, 2023
3rd Party API Consumption with D365FO
Prerequisite:
• Identify
the API name and purpose of API i.e., what it does?
• Identify
the endpoints.
• Understand
Request and Response JSON.
• Understand
the attributes used and consumed.
• Understand
the type of request i.e. GET, POST, PUT and Delete
• Understand
the criticality of each request.
• Understand
the error codes provided when there is any issue.
• Get
the details of the SSL Certificates which need to be utilized for consumption
of API and how can it be configured.
• Understand
If any IP Whitelisting is required and how can it be done.
• Understand
if there is any signed legal agreement is required in API templates.
Basic Architecture:
August 10, 2023
D365FO: Read CSV file from Azure File Share
using Microsoft.Azure;
using Microsoft.WindowsAzure.Storage;using Microsoft.WindowsAzure.Storage.Blob;using Microsoft.WindowsAzure.Storage.File;class MAKCloudStorageFileManager{ #File #define.delimiterField(',') public static void main(Args _args) { #OCCRetryCount System.IO.MemoryStream memoryStream; System.String storageAccountName; System.String keyValue; CloudStorageAccount storageAccount; CloudFileClient fileClient; CloudFileShare fileShare; CloudFileDirectory fileDirectoryRoot; CloudFileDirectory fileDirectory; CloudFile file; TextStreamIo textStreamIo; VendTable vendTable; VATNum vendABN; Counter counter; container rec; storageAccountName = "AzureStorageAccountName"; keyValue = "KeyValueString"; var storageCredentials = new Microsoft.WindowsAzure.Storage.Auth.StorageCredentials(storageAccountName, keyValue); storageAccount = new Microsoft.WindowsAzure.Storage.CloudStorageAccount(storageCredentials, true); fileClient = storageAccount.CreateCloudFileClient(); fileShare = fileClient.GetShareReference('AzureFileShareName'); if (fileShare.Exists(null, null)) { fileDirectoryRoot = fileShare.GetRootDirectoryReference(); fileDirectory = fileDirectoryRoot.GetDirectoryReference("Folder/Subfolder"); if (fileDirectory.Exists(null, null)) { file = fileDirectory.GetFileReference('File.csv'); if (file.Exists(null, null)) { memoryStream = new System.IO.MemoryStream(); file.DownloadToStream(memoryStream, null, null, null); textStreamIo = TextStreamIo::constructForRead(memoryStream); try { if (textStreamIo) { if (textStreamIo.status()) { throw Global::error("@SYS52680"); } textStreamIo.inFieldDelimiter(#delimiterField); textStreamIo.inRecordDelimiter(#delimiterCRLF); counter = 0; while (!textStreamIo.status()) { rec = textStreamIo.read(); if (conLen(rec)) { vendABN = conPeek(rec, 1); info(strFmt("%1", vendABN)); } } } } catch (Exception::Error) { error("An error occured. Please contact your system administrator."); } } } } }}

