Azure Blob Storage with Dynamics Portals

Portals and Documents

A common requirement with Dynamics Portals is allowing users to upload documents, such as attachments with regarding a Case. The standard method for this capability in Dynamics Portals is implemented via Notes:  Configure Notes on your portal form and users can upload files that are saved as a Note attachment.  Pretty cool and fairly easy to configure.  The downside of using notes for attachments include limitations on file size, storage costs, and potential performance hits on CRM.

Older versions of Adxstudio and Portals supported direct integration with SharePoint but that feature has since been deprecated. The preferred alternative to Notes attachments for document storage is to configure Azure Blob Storage.  With this option, your Portal will bypass a CRM attachment and save the uploaded file to an Azure Storage container, while providing the same experience to the portal user.

Azure Blob Storage Setup

Microsoft provides solid documentation at docs.microsoft.com for Dynamics Portals overall.  To configure Azure Blob Storage for your Portal, this article is your starting point: Enable Azure Storage.  This article provides a great starting point but I ran into some confusing bits while setting this up on my demo instance.  These instructions bounce around between how to configure your Azure account and how to configure CRM. So I wanted to provide a step by step guide to get this feature up and running in one place, including the steps to set up Azure Storage first and then steps to configure your Portal to leverage the new configuration.

Assumptions

This post assume you have an active Azure account and a CRM instance with a Portal up and running.  For this post, I am using a demo instance provisioned via https://demos.microsoft.com and I am deploying to the default Customer Self-Service Portal.  I also assume some familiarity with configuring Dynamics Portals and navigating your Azure account.  As stated, the documentation is pretty solid for configuring Dynamics Portals, but I will try and point out anything that might require some additional reading.

Also, a reminder that when changes are made to CRM forms, Entity forms, configuration, etc, you will need to invalidate the Portal Cache to see these changes immediately.  This tool can be found while logged into your portal as an Administrator at the following URL:

https://<your portal>.microsoftcrmportals.com/_services/about

Azure Storage Account

Storing files as an Azure Blob first requires setup of the Azure Storage Account.  This link referenced by the Enable Blob Storage article provide a lot of detail on how to configure Storage Containers, additional links, etc: About Azure storage accounts.  Creating the Azure Storage Account is relatively straight forward, but I missed a step when originally setting things up that cost me some time and confusion.

First, set up the Azure Storage Account via the Azure admin dashboard. Open the Storage Accounts section in your Azure Dashboard and choose New.

Azure Storage Account - Details

Most of these fields remained unchanged, such as Deployment Model (Resource Manager), Performance (Standard)  Secure transfer required (Disabled), etc. but some require new values.  You must provide a Name for the Storage account and specify a Resource Group. As displayed in a preview, the name builds the unique URL for your storage account, and I chose to create a new Resource Group called crm_blog_post. The other change here was to choose Blob Storage for the Account Kind value.

The documentation skips a bit that caused me an issue, which is the step to create a Container for your Storage Account.  For this step, just select Containers from the new Storage Account and choose the + to create a new Container and provide a new name.

Now that you have the Azure Storage Account and Container set up, you will need to configure the cross-origin resource sharing (CORS) rule.  This will be used as part of the authentication of your Portal as an outside application accessing your blob storage.  The article above provides the following information:

You must add cross-origin resource sharing (CORS) rule on your Azure Storage account as follows, otherwise you will see the regular attachment icon rather than the cloud icon:

  • Allowed origins: Specify your Dynamics 365 domain. For example, contoso.crm.dynamics.com.
  • Allowed verbs: GET, PUT, DELETE, HEAD, POST
  • Allowed headers: Specify the request headers that the origin domain may specify on the CORS request. For example, x-ms-meta-data*, x-ms-meta-target*.
  • Exposed headers: Specify the response headers that may be sent in the response to the CORS request and exposed by the browser to the request issuer. For example, x-ms-meta-*.
  • Maximum age (seconds): Specify the maximum amount time that a browser should cache the preflight OPTIONS request. For example, 200.

Another step that caused me issues was the Allowed Origins values.  When I uploaded a file, it worked correctly and the attachment was created within CRM as expected.  But when I viewed the file on the Case record, I was not seeing the actual file.  The Web Resource that renders the files in CRM (explained below) was failing when authenticating to the Azure Storage account.  So I had to add the full URL, not just the domain as in the instructions above.  So for my portal solution to work, I added the Allowed Origins in the format https://contoso.crm.dynamics.com. Once I updated the value with this format, the files rendered correctly on my CRM form.

For Allowed headers and Exposed headers settings, I saw a few posts that suggested using the wildcard * instead of the example above.  I am guessing that your project requirements will dictate what values you allow for these settings.

Connect Portals to Azure

Now that the Azure Storage Account is ready, you need to wire up your Portal with some settings to grant access to upload and read the files. These values will be added as new Settings and Site Settings records.  For the new Settings records, navigate to Settings -> Settings. This assumes the default sitemap provided with the Portals installation. You need to provide the following Settings values:

  • FileStorage/CloudStorageAccount – When you created the new Azure Storage Account, new Access Keys were generated automatically.  These keys are used for authenticating applications making requests to your Azure Storage Account and Container. Each key consists of a Key and Connection String. You will need to copy one of the Connection String values and enter that value as your new Setting record:

Copy Access Keys

New Access Key Setting Record

  • FileStorage/CloudStorageContainerName – This is the container name you created in the step that I missed above.

New Storage Container Setting Record

These two settings allow your Portal to authenticate and locate the correct Container in which it will place the uploaded files.  The next step will be to update Portal Site specific settings by adding two Site Settings records.  You can locate the site settings in the sitemap under Portals -> Site Settings.  As with the Settings, these are simple key / value pairs that you will add to each site for which these settings should apply.  The two values you need to add are:

  • WebFiles/CloudStorageAccount – This should include the same connection string that you entered for the FileStorage/CloudStorageAccount setting.  I am not quite sure why this value would need to be duplicated as it is already provided with the Settings record.
  • WebFiles/StorageLocation – This is a preset value if AzureBlobStorage indicating to the Portals solution that this Site is using Azure Blob Storage for file uploads.

New Site Settings Records

So the Settings values provided some overall Portal solution level values while these Site Settings records indicate to the Customer Self-Service Site that Azure Blob Storage has been enabled.

Enabling Upload to Azure Blob Storage from the Portal

Now that the connection between Azure Storage and your Portal and specific Site has been established, you will need to update your Portal screens to leverage this alternate method for file management.  For my testing, I focused on the Case entity.  So this meant an update to the Entity Form Metadata for the Case.

Navigate to Portals -> Entity Forms and open the Entity Form for Customer Service – Create Case for the Customer Self-Service Site. Under the Additional Settings tab, you will see the section titled Add Attach File.

Edit Entity Form - Create Case

In this section, change the value if Attach File Storage Location to Azure Blob Storage. I also changed the Attach File Save Option attribute to Notes so that I can view the files directly on the Case form.

Once you save the values, you can then view the Create Case form on your portal. There you will see the standard File Upload dialog at the bottom of the form.

Attach File(s)

When you hit submit, these files will now be directed to Azure Blob Storage rather than a Note attachment on the Case.  In this case, I selected two images to be uploaded when I submit.

Viewing uploaded files in CRM

Now you should have files in Azure when uploading from the portal, but how can you validate this?  Before opening the Case you just created from the Portal, you can check your Azure Storage Container to see if the file was uploaded.  Navigate to your Azure Storage Account and open the Storage Explorer tool, and under the Blob Containers choose the Container that you created and added to the settings previously.

Once selected, you will see a list of folders, and within the folder, your image that was uploaded.  So you have verified that the files are now being uploaded into Azure Blob Storage and not stored within a Note attachment, and the Note is no longer needed.

Well, not quite.  A little bit about the implementation…

When you open your case, you will see a new Note with an attachment in the Notes section for each file that was uploaded.  In my example above, I see the following.

Note Attachments on Upload

So uploaded files are not stored as Note attachments, but the Portal solution still leverages a Note attachment to connect the Case to the file in Azure Blob Storage.  Opening one of the attachments, you can see that it contains a simple JSON segment that provides the link to the uploaded image:

{
    "Name": "jen flower.jpg",
    "Type": "image/jpeg",
    "Size": 80469,
    "Url": "https://mycrmblobstorage.blob.core.windows.net/_
            mycrmblobstoragecontainer/9d46d221c65be811a95a000d3aa2c251/jen%20flower.jpg"
}

In order to view the file from within CRM as opposed to the attached text file, a web resource has been included as part of the portal solution.  The article titled Add the Azure Storage web resource to a form does a good job outlining how to add this to your form to view the files, providing the web resource schema name, some details on it’s function, and the parameters required to ensure it is enabled correctly.

This step is standard CRM configuration, just adding a web resource to an Entity form, so I will not outline those details again in this post.  In my testing, I simply added it to the Case form because I changed the settings in the Entity Form definition to leverage Notes instead of the Comments entity.  When I load the Case, I see the following list of files:

Azure Blob Web Resource

Each file is listed with a cloud icon next to the name indicating that the file is hosted in an Azure Storage Account, and each provides a link to open the file in a new window.  Here CRM users can also add their own files to Azure Blob Storage from the Case form.  The web resource mimics the Note create functionality to allow the file upload to Azure. 

Notice the cloud icon again that indicates this file will be stored in Azure as opposed to a Note attachment.  Once you choose Done, the new file will be persisted on Azure Blob Storage instead of a Note attachment. As the article above suggests, you will probably want to hide the Notes tab in the Activities pane to avoid confusion and leverage this web resource as a replacement.

Viewing uploaded files from the Portal

Now you should be able to upload files to Azure Blob Storage from the Portal and then both view and upload files to a Case from within CRM, you now likely need to enable viewing the files from the Portal when editing an existing Case.  This involves an update to the Entity Form as well as the CRM form.

I started with the default configuration for the Customer Self-Service portal where Cases are configured to use the Portal Comment entity for capturing feedback and file uploads.  Shifting to use Notes on the Case directly meant a change to the Activities control on the CRM form referenced by the Entity Form named Web – Edit Case. The settings needed to now use Notes so that the Portal would render the list of files correctly, rather than the previously configured Portal Comment activity.

Activities Tab - UI

Activities Tab - Web Client

Once the CRM form is saved and published, you will need to make an update to the Entity Form configured for editing a Case on the Portal, Customer Service – Edit Case.  This is an almost identical update as was made to the Customer Service – Create Case Entity Form.

Edit Entity Form - Edit Case

Once you save this last update and invalidate the Portal Cache, you should can then view the files uploaded to the Case.

View Files on Case in Portal

Summing up

The initial setup and configuration to enable Azure Blob Storage for a Dynamics Portal is relatively straightforward:  set up the Azure Storage Account, add some Portal level Settings, then add Site Settings.  From there, it gets a bit more involved.  Each entity and portal location that should leverage the Azure Blob Storage will require some configuration.  This can be a bit time consuming at first but once you understand the moving parts, it’s just a matter of making the changes where needed.

It is also interesting to note how the storage was implemented.  This solution simply leverages the existing Note entity and its relation to a parent entity. Taking a quick look at the web resource and supporting scripts, it looks like the file upload to Azure Blob Storage is handled on the clients side via JavaScript. I am curious how large files are handled, such as large video files.  It looks like the solution has been around for a while (Copyright (c) 2014 in the source!) so I would guess this has been tested against large files.

I am also curious about cleanup of these files.  I see code to handle the delete of the Note attachment in the supporting scripts, but I have not looked at what happens when you delete an attachment directly.  Will you have orphaned files in Azure, or does the Portal solution include plugins that handle the delete and subsequent cleanup of the files?

These should be relatively easy to test and verify, but they should be some of the many considerations when choosing a solution for file management.

Additional Reading

Below is a summary of a few of the articles I referenced during my testing, some referenced above and others highlighted within these articles.

 

As always, comments, suggestions, corrections, and questions are always welcome.  Please let me know if I missed any steps here or you have some experience on this topic that you would like to share


Leave a Reply

Your email address will not be published. Required fields are marked *