File storage solutions in Model-Driven App scenarios

Whenever we design software systems, it is crucial to create and manage documents in a way that makes them accessible through the UI in a streamlined fashion - ideally without leaving the system boundaries. So, let's take a look at different file storage solutions and how they can be applied in your model-driven app scenario.

SharePoint Online Integration

Since the early Dynamics Customer Engagement times, you could store files through a model-driven app by using the built-in SharePoint integration. Meaning you can access files through the documents grid in the model-driven app in the context of a record:

Show files stored in SharePoint in a model-driven app. ... or by opening the menu Related ➡️Documents: Show files backed in SharePoint document library. ... as well as via SharePoint Document Library:

Show files backed in SharePoint document library. The SharePoint integration can bei configured for standard and custom tables and is only limited by the restrictions of the underlying SharePoint.

Integrate documents subgrid on the main form

Your users might find it too difficult or inefficient to navigate to the files tab everytime they need to view a document. In this case, try this more user-friendly approach and directly embed the documents subgrid on a main form's section as subgrid. This is not possible through the app designer but needs to be done directly by manipulating the form xml as described in the docs: Add the Documents tab to the main form for a table.

<control id="DocumentSubGrid" classid="{E7A81278-8635-4d9e-8D4D-59480B391C5B}" indicationOfSubgrid="true" uniqueid="{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}"> <parameters> <ViewId>{0016F9F3-41CC-4276-9D11-04308D15858D}</ViewId> <IsUserView>false</IsUserView> <RelationshipName>Account_SharepointDocument</RelationshipName> <TargetEntityType>sharepointdocument</TargetEntityType> <AutoExpand>Fixed</AutoExpand> <EnableQuickFind>false</EnableQuickFind> <EnableViewPicker>true</EnableViewPicker> <ViewIds /> <EnableJumpBar>false</EnableJumpBar> <ChartGridMode>Grid</ChartGridMode> <VisualizationId /> <IsUserChart>false</IsUserChart> <EnableChartPicker>false</EnableChartPicker> <RecordsPerPage>10</RecordsPerPage> <HeaderColorCode>#F3F3F3</HeaderColorCode> </parameters> </control>

All files will be grouped under the context of a specific Dataverse record and displayed in a list. While this tackles many document management challenges, it can definitely make things difficult if you want to be able to associate a certain document type (e.g., a contract, final quote document, etc.) on a record and want to make this information accessible through business logic. For example, allow proceeding of Business Process Flow only if a certain document is provided. Let's take a look at how to handle that situation in the next section.

Dataverse File Type Column

Dataverse has a dedicated File Datatype column that allows storage of a single file. This file is rendered as a regular control and can be placed directly on the form. As you can see from the screenshot, you could even set business required field levels as well as file size upper boundaries. Show files backed in SharePoint document library. File upload via the webclient is limited to 128 MB, though via the API it is possible to store up to 10 GB. You can globally restrict the permitted filetype through the system settings general tab. Show files backed in SharePoint document library.

Interaction server side

You can access the uploaded binary data by using a Power Automate flow with the Download a file or an image action. Alternatively, WebAPI Actions will allow you to download or upload files. Large uploads can be split into chunks to work more reliably.

Sample code for upload and download: Use file column data (Microsoft Dataverse)

The following messages are available for interacting with file type column data:

Upload

Download

For additonal information regarding the datamodel behind the file type, you can find details in the docs.

I would like to highlight that the stored files do not consume database capacity as they are using the file capacity of the Dataverse storage system.

Interaction client side

The attribute on the form can be queried just like a regular column. Executing formContext.getAttribute('new_filetypecolumn').getValue(); will present the following information about the uploaded file:

{ "attributeName": "new_filetypecolumn", "fileName": "Lieferschein Nr. 2022122901.pdf", "fileSize": 213212, "fileUrl": "https://orgname.crm4.dynamics.com/api/data/v9.0/accounts(8f5b9adb-79a8-ed11-aad1-0022489c4f48)/new_filetypecolumn/$value", "mimeType": "application/pdf" }

Accessing the url in fileUrl property allows downloading the file directly.

Conclusion

When designing the file storage solution for your app, consider whether information about the existence of specific documents is required, as they might be associated with events in your business logic. If so, you should prefer using a file type column since querying and accessibility are far easier.

On the other hand, if you need to store multiple files for a record or need even more advanced capabilities like SharePoint’s full text search or collaborative functionality on Microsoft Office file types, then SharePoint Document Integration is definitely the way to go.

P.S. If you found this article helpful, be sure to also learn how to Automatically create subfolders in SharePoint after record is saved in a model-driven App.


Blog post written by

Marius Pothmann

Marius Pothmann is a Microsoft certified solution architect focusing on the Power Platform and cloud-native application development on Azure. Working on the Microsoft stack for over a decade gave him the opportunity to deep dive into many building blocks of successful enterprise application architectures like Dynamics 365, SQL Server, ADFS, ASP.NET (Core), SPA-based Web Apps, WPF/WinForms. If you think he can assist in solving your challenges drop us an e-mail and we will get back to you right away.