Dynamics 365 Business Central: custom Onedrive integrations

Dynamics 365 Business Central 2022 Wave 1 (version 20) enhanced the integration with Onedrive for Business, the cloud storage service that is included in Microsoft 365. Business Central v20 makes now very easy to store, manage, and share files with other people through OneDrive with a set of predefined actions that you can have on some entities, for example Attachments:

As standard, you can find these actions on most pages where files are available for downloading.

When I’ve done the File Management webcast for Aeropa some months ago, I’ve done a quick demo about how you can use the new Onedrive features also from your custom extensions and on custom entities and someone of you asked me more informations about this. The code was shared with attendees, but now I want to create a public post about this nice new feature.

Imagine that I want to add the Onedrive integration to my Sales Order entity. I want to be able to open a Sales Order document in Onedrive and share a Sales Order document through Onedrive to other users. How can I do that?

Before starting, I think it’s important to specify that the document sharing and OneDrive capabilities are divided between the System application and the Base application. In particular:

  • The System application provides the document sharing functionalities via the Document Sharing module, that consists of two public objects:
    • Table Document Sharing: temporary table that stores state information about the document to be shared.
    • Codeunit Document Sharing: code that performs the document sharing by using a temporary instance of the Document Sharing table.
  • The Base application uses the Document Sharing module and makes it specific to OneDrive. In particular:
    • Codeunit Document Service Management contains 4 procedures for handling the document sharing in Onedrive via the Document Sharing module.

How to create a custom integration with Onedrive?

The Onedrive integration user experience should be consistent across the application, so it’s important to follow some basic rules about using captions, images and visibility.

To add the Onedrive integration in my Sales Order page, I need to create a pageextension object and here add the two actions:

  • Open in Onedrive: calls the OpenInOneDrive(FileName: Text; FileExtension: Text; InStream: InStream) method of the Document Service Management codeunit for copying documents stored as BLOBs to OneDrive and opening the documents.
  • Share in Onedrive: calls the ShareWithOneDrive(FileName: Text; FileExtension: Text; InStream: InStream) of the Document Service Management codeunit for copying documents stored as BLOBs to OneDrive and sharing the documents with other people.

The extension’s code is as follows:

pageextension 50100 SDSalesOrderExt extends "Sales Order"
{
    actions
    {
        addlast("O&rder")
        {
            action(SDOpenInOneDrive)
            {
                // The properties provide a look and feel that's consistent with the OneDrive experience in other places of the base application.
                ApplicationArea = Basic, Suite;
                Caption = 'Open in OneDrive';
                ToolTip = 'Copy the file to your Business Central folder in OneDrive and open it in a new window so you can manage or share the file.';
                Image = Cloud;
                Promoted = true;
                PromotedCategory = Category6;
                PromotedOnly = true;

                // Enables the action if connection is enabled.
                Enabled = ShareOptionsEnabled;

                trigger OnAction()
                var
                    TempBlob: Codeunit "Temp Blob";
                    DocumentServiceManagement: Codeunit "Document Service Management";
                    InStr: InStream;
                begin
                    GetSalesOrder(TempBlob);

                    TempBlob.CreateInStream(InStr);

                    // Helper to invoke document sharing flow
                    DocumentServiceManagement.OpenInOneDrive(StrSubstNo(SalesOrderName, Rec."No."), '.pdf', InStr);
                end;
            }

            action(SDShareInOneDrive)
            {
                // The properties provide a look and feel that's consistent with the OneDrive experience in other places of the base application.
                ApplicationArea = Basic, Suite;
                Caption = 'Share';
                ToolTip = 'Copy the file to your Business Central folder in OneDrive and share it with other people.';
                Image = Share;
                Promoted = true;
                PromotedCategory = Category6;
                PromotedOnly = true;

                // Enables the action if connection is enabled.
                Enabled = ShareOptionsEnabled;

                trigger OnAction()
                var
                    TempBlob: Codeunit "Temp Blob";
                    DocumentServiceManagement: Codeunit "Document Service Management";
                    InStr: InStream;
                begin
                    GetSalesOrder(TempBlob);

                    TempBlob.CreateInStream(InStr);

                    // Helper to invoke document sharing flow
                    DocumentServiceManagement.ShareWithOneDrive(StrSubstNo(SalesOrderName, Rec."No."), '.pdf', InStr);
                end;
            }
        }
    }

    var
        ShareOptionsEnabled: Boolean;
        SalesOrderName: Label 'Sales Order %1';


    trigger OnOpenPage();
    var
        DocumentSharing: Codeunit "Document Sharing";
    begin
        ShareOptionsEnabled := DocumentSharing.ShareEnabled();
    end;

    local procedure GetSalesOrder(var TempBlob: Codeunit "Temp Blob")
    var
        ReportSelections: Record "Report Selections";
        RecRef: RecordRef;
    begin
        RecRef.GetTable(Rec);
        RecRef.SetRecFilter();

        ReportSelections.GetPdfReportForCust(TempBlob, ReportSelections.Usage::"S.Order", RecRef, Rec."Sell-to Customer No.");
    end;
}

As you can see, in both actions the GetSalesOrder procedure takes the stream of the document to share and then the right method of the Document Service Management codeunit is called.

When you publish this extension, you have two new actions added into the Sales Order page:

When you select the Open in Onedrive action, the document is uploaded to the Business Central folder in Onedrive and opened:

If you have previously opened the document in Onedrive, the code asks you if you want to replace the file or create a copy of the file:

If you click the Share action, the document is uploaded in Onedrive and a Onedrive share link action appears to the user. Here the user can share the document with other users or create a public link to send to externals:

Some important things to mention about the integration pattern:

  • the visibility of the actions should be conditioned to a Boolean variable returned by the ShareEnabled method of the Document Sharing module. This method returns true if Document Sharing is enabled in your environment.
  • You cannot move files to Onedrive in a background task, the integration pattern is designed for user interaction.
  • In a later CU/Release you will have an improved support to specify file names and folder names in Onedrive when sharing files (actually this can be done only by tweeking in the Document Sharing temporary table).

2 Comments

  1. To me this seems like the attached document gets saved in the Database. If you push the file to OneDrive, now you have the document saved in the database and OneDrive.

    Is there any option to only have the files saved in OneDrive, and not saved in the Database? Want to reduce the database getting to big with file attachment.

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.