Skip to content

Conversation

@StefanSosic
Copy link
Contributor

@StefanSosic StefanSosic commented Aug 21, 2025

Summary

Document Attachments External Storage for Microsoft Dynamics 365 Business Central

Overview

The External Storage extension provides seamless integration between Microsoft Dynamics 365 Business Central and external storage systems such as Azure Blob Storage, SharePoint, and File Shares. This extension automatically manages document attachments by storing them in external storage systems while maintaining full functionality within Business Central.

Key Features

Automatic Upload

  • Automatically uploads new document attachments to configured external storage
  • Supports multiple storage connectors via the File Account framework
  • Generates unique file names to prevent collisions
  • Maintains original file metadata and associations

Flexible Deletion Policies

  • Immediately: Delete from internal storage right after external upload
  • 1 Day: Keep internally for 1 day before deletion
  • 7 Days: Keep internally for 7 days before deletion (default)
  • 14 Days: Keep internally for 14 days before deletion

Bulk Operations

  • Synchronize multiple files between internal and external storage
  • Bulk upload to external storage
  • Bulk download from external storage
  • Progress tracking with detailed reporting

Installation & Setup

Prerequisites

  • Microsoft Dynamics 365 Business Central version 27.0 or later
  • File Account module configured with external storage connector
  • Appropriate permissions for file operations

Installation Steps

  1. Configure File Account

    • Open File Accounts page
    • Create a new File Account with your preferred connector:
      • Azure Blob Storage
      • SharePoint
      • File Share
    • Assign the account to External Storage scenario
  2. Configure External Storage

    • Open File Accounts page
    • Select assigned External Storage scenario
    • Open Additional Scenario Setup
    • Configure settings:
      • Auto Upload: Enable automatic upload of new attachments
      • Delete After: Set retention policy for internal storage

Configuration Options

Auto Upload Settings

  • Enabled: New document attachments are automatically uploaded to external storage
  • Disabled: Manual upload required via actions

Usage

Automatic Mode

When Auto Upload is enabled:

  1. User attaches a document to any Business Central record
  2. System automatically uploads to external storage
  3. File remains accessible through standard attachment functionality
  4. Internal file is deleted based on configured retention policy

Manual Operations

Individual File Operations

From Document Attachment - External page:

  • Upload to External Storage: Upload selected file
  • Download from External Storage: Download file for viewing
  • Download to Internal Storage: Restore file to internal storage
  • Delete from External Storage: Remove file from external storage
  • Delete from Internal Storage: Remove file from internal storage

Bulk Operations

From External Storage Synchronize report:

  • To External Storage: Upload multiple files to external storage
  • From External Storage: Download multiple files from external storage
  • Delete Expired Files: Clean up files based on retention policy

File Access

  • Files uploaded to external storage remain fully accessible through standard Business Central functionality
  • Document preview, download, and management work seamlessly
  • No change to end-user experience

© 2025 Microsoft Corporation. All rights reserved.

Work Item(s)

Fixes AB#592686

Fixes #4494

@StefanSosic StefanSosic requested a review from a team as a code owner August 21, 2025 14:35
@github-actions github-actions bot added AL: System Application From Fork Pull request is coming from a fork labels Aug 21, 2025
@pri-kise
Copy link
Contributor

@StefanSosic could maybe elaborate a little bit on your events.
Personally I'm not a real fan of the IsHandled Events.

Couldn't we solve this by adding an well designed interface to the FileScenario..
We could have DefaultImplementation that does nothing.
If an enum value implements this interface then we would be able to Call Methods for the relevant enum value.

Maybe something like the following

interface FileScenario

procedure HasAdditionalSetup(): Boolean
procedure OpenAdditionalSetup(TBDParameters)
procedure CheckScenarioBeforeDeletion()
...

Maybe you could show some example code how you would like to subscribe to this in the Microsoft BaseApp.
This could help finding a good design for the System Application.

@StefanSosic
Copy link
Contributor Author

@StefanSosic could maybe elaborate a little bit on your events. Personally I'm not a real fan of the IsHandled Events.

Couldn't we solve this by adding an well designed interface to the FileScenario.. We could have DefaultImplementation that does nothing. If an enum value implements this interface then we would be able to Call Methods for the relevant enum value.

Maybe something like the following

interface FileScenario

procedure HasAdditionalSetup(): Boolean
procedure OpenAdditionalSetup(TBDParameters)
procedure CheckScenarioBeforeDeletion()
...

Maybe you could show some example code how you would like to subscribe to this in the Microsoft BaseApp. This could help finding a good design for the System Application.

The events created are providing possibility for additional control, which is not mandatory. That's why it's by design with events, not interface. This module is specific and we wanted to put disclaimer message before adding scenario and so on, but I think lot of scenarios won't use that feature.

Setup action is using event as discovery method. Again, not mandatory to have and implement setup, that's why didn't went with interfaces. I did had a call to align with the concept, and events were mentioned.

Let me try to bring more context to it, implementation of File Accounts with Scenarios shouldn't be limited to Base App and internal development, but give partners possibility to adjust and work on their own scenarios.

GetAdditionalScenarioSetup - Discovery event if there is additional setup for a scenario, must not be existing
BeforeDeleteFileScenarioCheck - Is there any restriction when deleting scenario, additional checks, in this case if files are already uploaded you can't unassign until all files are back to internal storage
BeforeAddOrModifyFileScenarioCheck - When adding scenario, additional checks or so, in this case disclaimer message

For scenarios, we already have default one. In this case, this are optional features, which I see more that they won't end being used then they will, if they will it will be implemented one of these three for example. Don't want to implement interface and to use just one of the procedures, rest needs to be handled unnecessary. But I got your point, interface is nice and good, but just for this case I don't see it fitting, just because of type of procedures to be used. My scenario is for Document Attachments, but it could be just anything, Email, Sms, Backup, anything, in those case this interface procedure wouldn't make any sense. We need to look for a full picture and wide spectrum of implementation of File Scenarios and that could be anything.

Module is generally done and PR's created, Jesper will take it for a spin on Monday.
Here are PR's:
System Application adjustments for External Storage Module:
Extensibility adjustments to File Account module in order for External Storage module by StefanSosic · Pull Request #4495 · microsoft/BCApps

Base Application adjustments for External Storage Module:
Extensibility adjustments to File Account module in order for External Storage module by StefanSosic · Pull Request #1538 · microsoft/BusinessCentralApps

AL App Extension - Full Module:
External Storage - Document Attachments by StefanSosic · Pull Request #29087 · microsoft/ALAppExtensions

I am open for suggestions, keep in mind that this is first version, this is just handful of functionality, no need to introduce more and more, since we plan to push it to preview asap.

And as you can see, point is to provide this as separate extension, and this should be also an demo for partners, how to implement their own File Scenario for any need.

Copy link
Contributor

@TKapitan TKapitan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am voting against these changes due to security risks. It's similar to discussion a few years back when similar events were discussed for Email Scenarios. This would allow anyone to block deletion or disabling of custom connectors and exposing too much control to PTE and ISV solutions for custom File Connectors.

If we want to have this ability in place, it should use interfaces so extensions are able to manage only own implementations not implementations from other partners.

These events basically cancel the generic approach for scenarios where the scenarios should be independent and secure from third-party injections. This is considered as one of the main advantages of scenarios where the implementation enforce some level of security of what is exposed and what other extensions can change. This implementation basically removes this control from partners and introduce (in my opinion) bad IsHandled pattern in place where it should not be used.

@pri-kise @StefanSosic

@JesperSchulz Please review this design before adding it to the product, these IsHandled in System Apps are not a good choice especially for modular apps. It was discussed in the past how "bad" the IsHandled pattern is and adding it to generic scenario extension is just wrong.

@tonyabriccomeske
Copy link

If we want to have this ability in place, it should use interfaces so extensions are able to manage only own implementations not implementations from other partners.

These events basically cancel the generic approach for scenarios where the scenarios should be independent and secure from third-party injections. This is considered as one of the main advantages of scenarios where the implementation enforce some level of security of what is exposed and what other extensions can change. This implementation basically removes this control from partners and introduce (in my opinion) bad IsHandled pattern in place where it should not be used.

We should be advocating for more sophisticated code, especially in these main apps. Otherwise we end up with a lot of "IsHandled" patterns in PTEs, without thinking about the repercussions.

@JesperSchulz JesperSchulz added the Integration GitHub request for Integration area label Aug 25, 2025
@JesperSchulz JesperSchulz self-assigned this Aug 25, 2025
@StefanSosic StefanSosic requested review from a team as code owners August 25, 2025 12:44
@StefanSosic StefanSosic changed the title Extensibility adjustments to File Account module in order for External Storage module External Storage - Document Attachments Aug 25, 2025
@github-actions github-actions bot added the Linked Issue is linked to a Azure Boards work item label Aug 25, 2025
@github-actions github-actions bot added this to the Version 27.0 milestone Aug 25, 2025
@StefanSosic
Copy link
Contributor Author

@TKapitan @pri-kise @tonyabriccomeske
Hi, we made a decision to go with interfaces. It's implemented at this point

Copy link
Contributor

@pri-kise pri-kise left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should have some test coverage for this new functionality.

I don't know if we already have a mocking Storage in the System Application, but we could add this here.

For starters I'm thinking about the following test cases

// [GIVEN] Mocked External Storage (Maybe via a internal table or single instance codeunit)
// [GIVEN] Valid Setup for Document Attachments Exteranl Storage provided
// [GIVEN] Document Attachment is created
// [WHEN] Document Attachment sync runs
// [THEN] Verify Document Attachment is updated correctly

The following test case is an example for one procedure of the document attachment.

// [GIVEN] Mocked External Storage
// [GIVEN] Valid Setup for Document Attachments Exteranl Storage provided
// [GIVEN] Document Attachment is created
// [GIVEN] Document Attachment synced
// {WHEN] TemplBlob is retrieved via procedure from Document Attachment 
// [THEN] Verify TempBlob

We should have tests for all the procedures that we handle.

Copy link
Contributor

@pri-kise pri-kise left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We might need to condsider to add extensions for some Entitlements.

@github-actions github-actions bot added the AL: Apps (W1) Add-on apps for W1 label Oct 21, 2025
@StefanSosic
Copy link
Contributor Author

I'd like to point out that all comments from the review have been addressed.

Managed to accomplish copy company/environment/tenant
Thanks to Tom for sharing idea how it was handled in their case. I came up with something little bit different but on principe same read-only and when copy if desctructive change or modify, it needs migration first

Copy link
Contributor

@pri-kise pri-kise left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should have some test coverage for this new functionality.

I don't know if we already have a mocking Storage in the System Application, but we could add this here.

For starters I'm thinking about the following test cases

// [GIVEN] Mocked External Storage (Maybe via a internal table or single instance codeunit)
// [GIVEN] Valid Setup for Document Attachments Exteranl Storage provided
// [GIVEN] Document Attachment is created
// [WHEN] Document Attachment sync runs
// [THEN] Verify Document Attachment is updated correctly

The following test case is an example for one procedure of the document attachment.

// [GIVEN] Mocked External Storage
// [GIVEN] Valid Setup for Document Attachments Exteranl Storage provided
// [GIVEN] Document Attachment is created
// [GIVEN] Document Attachment synced
// {WHEN] TemplBlob is retrieved via procedure from Document Attachment 
// [THEN] Verify TempBlob

We should have tests for all the procedures that we handle.

@fvet
Copy link
Contributor

fvet commented Nov 28, 2025

@StefanSosic

The other issue that seems not solved are shared references and problem of deleting file in shared reference. By shared reference I mean document attachments that target the same external file (e.g. when you have attachment configured to flow to sales, purchase etc. documents).

I certainly welcome this new module and am happy the copy environment issue is supported.
The one major issue we still see is the optional use of the 'Delete from External Storage' setting, combined with shared references.

...The other issue that seems not solved are shared references and problem of deleting file in shared reference. By shared reference I mean document attachments that target the same external file (e.g. when you have attachment configured to flow to sales, purchase etc. documents)...

There tens of occurences ('flow to sales', quote to order, posting invoice, ...) in the Base App copying attachments (using Transferfields) between entities, resulting in multiple document attachments, referencing the same external path.

image image

Any plans from MS on at least providing native support for this scenario?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

AL: Apps (W1) Add-on apps for W1 AL: System Application From Fork Pull request is coming from a fork Integration GitHub request for Integration area Linked Issue is linked to a Azure Boards work item

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BC Idea]: Extensibility adjustments to File Account module in order for External Storage module

10 participants