Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Conferences
Free Learning
Arrow right icon
Arrow up icon
GO TO TOP
Mastering Microsoft Dynamics 365 Business Central

You're reading from   Mastering Microsoft Dynamics 365 Business Central The complete guide for designing and integrating advanced Business Central solutions

Arrow left icon
Product type Paperback
Published in Mar 2024
Publisher Packt
ISBN-13 9781837630646
Length 684 pages
Edition 2nd Edition
Languages
Arrow right icon
Authors (2):
Arrow left icon
Stefano Demiliani Stefano Demiliani
Author Profile Icon Stefano Demiliani
Stefano Demiliani
Duilio Tacconi Duilio Tacconi
Author Profile Icon Duilio Tacconi
Duilio Tacconi
Arrow right icon
View More author details
Toc

Table of Contents (21) Chapters Close

Preface 1. Microsoft Dynamics 365 Business Central’s Online Momentum 2. Mastering a Modern Development Environment FREE CHAPTER 3. Extension Development Fundamentals 4. Developing a Customized Solution for Dynamics 365 Business Central 5. Writing Code for Extensibility 6. Advanced AL Development 7. Handling Files with Dynamics 365 Business Central 8. Report Development 9. Printing 10. Debugging 11. Telemetry 12. Coding for Performance 13. Dynamics 365 Business Central APIs 14. Extending Dynamics 365 Business Central with Azure Services 15. DevOps for Dynamics 365 Business Central 16. Dynamics 365 Business Central and Power Platform Integration 17. Useful and Proficient Tools for AL Developers 18. Creating Generative AI Solutions for Dynamics 365 Business Central 19. Other Books You May Enjoy
20. Index

Understanding Isolated Storage

Isolated Storage is key-value-based storage that provides data isolation between extensions. Isolated Storage can be used to store data that must be preserved inside the extension scope, and this data is accessible via AL code by using the IsolatedStorage data type. The DataScope option of the IsolatedStorage data type identifies the scope of stored data in Isolated Storage.

DataScope is an optional parameter and the default value is Module. All possible values are listed in the following table:

Member

Description

Module

It indicates that the record is available in the scope of the app context.

Company

It indicates that the record is available in the scope of the company within the app context.

User

It indicates that the record is available for a user within the app context.

CompanyAndUser

It indicates that the record is available for a user and specific company within the app context.

Table 6.2 – DataScope parameter values

To manage data with the IsolatedStorage data type, you have the following methods:

Method

Description

[Ok := ] IsolatedStorage.Set(Key: String, Value: String, [DataScope: DataScope])

This sets the value associated with the specified key within the extension. The optional DataScope parameter is the scope of the stored data.

[Ok := ] IsolatedStorage.Get(Key: String, [DataScope: DataScope], var Value: Text)

This gets the value associated with the specified key within the extension. The optional DataScope parameter is the scope of the data to retrieve.

HasValue :=  IsolatedStorage.Contains(Key: String, [DataScope: DataScope])

This determines whether the storage contains a value with the specified key within the extension. The optional DataScope parameter is the scope to check for the existence of the value with the given key.

[Ok := ] IsolatedStorage.Delete(Key: String, [DataScope: DataScope])

This deletes the value with the specified key from the Isolated Storage within the extension. The optional DataScope parameter is the scope to remove the value with the given key.

Table 6.3 – IsolatedStorage data type methods

Isolated Storage is useful to store sensitive data, user options, and license keys.

Let’s consider the following example:

local procedure IsolatedStorageTest()
    var
        keyValue: Text;
    begin
        IsolatedStorage.Set('mykey','myvalue',DataScope::Company);
        if IsolatedStorage.Contains('mykey',DataScope::Company) then
        begin
            IsolatedStorage.Get('mykey',DataScope::Company,keyValue);
            Message('Key value retrieved is %1', keyValue);
        end;
        IsolatedStorage.Delete('mykey',DataScope::Company);
    end;

From the preceding code, we get the following:

  1. IsolatedStorage.Set: In the first step, we save, in Isolated Storage, a key called mykey with a value of myvalue and DataScope set to Company. The key is visible in the scope of the company within the app context, so no other extensions can access this key.
  2. IsolatedStorage.Get: In the second step, we check whether a key called mykey is saved in Isolated Storage with DataScope set to Company. If a match is found (key and scope), the key is retrieved (with the Get method) and the value is returned in the keyValue text variable.
  3. IsolatedStorage.Delete: In the last step, we delete the key for this DataScope.

As previously said, you could also use Isolated Storage to save license keys or license details for your extension. The following code shows how to export the records of a table called License to JSON, then how to encrypt the JSON value, and finally, how to store the encrypted text in Isolated Storage:

local procedure StoreLicense()
    var
        StorageKey: Text;
        LicenseText: Text;
        EncryptManagement: Codeunit "Cryptography Management";
        License: Record License temporary;
    begin
        StorageKey := GetStorageKey();
        LicenseText := License.WriteLicenseToJson();
        if EncryptManagement.IsEncryptionEnabled() and EncryptManagement.IsEncryptionPossible() then
            LicenseText := EncryptManagement.Encrypt(LicenseText);
        if IsolatedStorage.Contains(StorageKey, DataScope::Module) then
            IsolatedStorage.Delete(StorageKey);
        IsolatedStorage.Set(StorageKey, LicenseText, DataScope::Module);
    end;
    local procedure GetStorageKey(): Text
    var
        //Returns a GUID
        StorageKeyTxt: Label 'dd03d28e-4acb-48d9-9520-c854495362b6', Locked = true;
    begin
        exit(StorageKeyTxt);
    end;
    local procedure ReadLicense()
    var
        StorageKey: Text;
        LicenseText: Text;
        EncryptManagement: Codeunit "Cryptography Management";
        License: Record License temporary;
    begin
        StorageKey := GetStorageKey();
        if IsolatedStorage.Contains(StorageKey, DataScope::Module) then
            IsolatedStorage.Get(StorageKey, DataScope::Module, LicenseText);
        if EncryptManagement.IsEncryptionEnabled() and EncryptManagement.IsEncryptionPossible() then
            LicenseText := EncryptManagement.Decrypt(LicenseText);
        License.ReadLicenseFromJson(LicenseText);
    end;

Here, the License table is declared as a temporary table. This way, the data is isolated in the calling codeunit.

Related to secret management with Isolated Storage, remember that:

  • In Dynamics 365 Business Central SaaS, sensitive data stored in Isolated Storage is always encrypted.
  • In Dynamics 365 Business Central on-premises, encryption is controlled by the end user (via the Data Encryption Management page):
    • If encryption is turned on, a secret stored in Isolated Storage is automatically encrypted.
    • A secret that was inserted while encryption was turned off will remain unencrypted if encryption is turned on.
    • If you turn off encryption, the secret will be decrypted.

According to these changes, if you have an extension that works for Dynamics 365 Business Central SaaS and on-premises and you’re using Isolated Storage to store secrets, you need to check whether encryption is enabled (which is always true for SaaS) and then save the secret accordingly.

So, a function that saves a license key to Isolated Storage and works for Dynamics 365 Business Central SaaS and on-premises will be as follows:

local procedure StoreLicense()
var
   licenseKeyValue: Text;
begin
   if not EncryptionEnabled() then
       IsolatedStorage.Set('LicenseKey',licenseKeyValue,DataScope::Module)
   else         
      IsolatedStorage.SetEncrypted('LicenseKey',licenseKeyValue,DataScope::Module)
end;

With the SetEncrypted method, you can now automatically save a secret by using encryption (no more calls to the Cryptography Management codeunit).

We have seen how to use Isolated Storage to improve data security in our extensions. In the next section, we’ll see how to create control add-ins.

lock icon The rest of the chapter is locked
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $19.99/month. Cancel anytime