Alternatives of Document storage in Dynamics CRM


CRM space is expensive, and often clients want alternatives to CRM storage for storing documents, images as these take up most of the space.

Available solutions:

  1. SharePoint Online with Dynamics CRM
  2. OneDrive for Business with Dynamics CRM

Currently, SharePoint document management is the preferred choice for most of the customers as alternative to storing email attachments and documents.

Advantages of SharePoint:

  1. SharePoint storage cost is very small about $0.20 per GB/Month compared to CRM’s $9.99/GB/Month. So CRM space is around 50 times costlier than SharePoint space.
  2. You can leverage SharePoint Document management features like:
    1. Full text Search
    2. Metadata sorting
    3. Revisions
    4. Enterprise grade security

There are 2 ways to use SharePoint for document management with Dynamics:

  1. Use SharePoint Online Integration with Dynamics CRM. This is the ideal and efficient way to use SharePoint. You can see the steps for SharePoint online integration in one of our previous blogs:

  1. Use 3rd Party tools like Power Attachment, which will migrate your File attachments (notes) and Email attachments from CRM storage to Dynamics.

More detail and pricing about Power attachments can found here:

1st approach should be the preferred way for using SharePoint as it is free, and works well. But users complain about an extra step to navigate to attachments, in which case you can go for Approach 2.

Alternative Solution:

  • The drawback with using SharePoint is if you have requirement of migrating your documents from CRM storage (Notes Attachments and Email attachments), you need to use 3rd party paid tools like Power Attachment.
  • Developing custom plugins to migrate documents to SharePoint is difficult in CRM online, since we cannot use External libraries in Sandbox plugin.

Due to above 2 reason, we can use Azure Blob storage as a possible alternative for migrating CRM documents.

What is Azure Blob storage:

Massively-scalable object storage for unstructured data

With exabytes of capacity and massive scalability, Azure Blob storage easily and cost-effectively stores from hundreds to billions of objects, in hot or cool tiers depending on how frequently data access is needed. Store any type of unstructured data—images, videos, audio, documents and more.

Azure Blob Features:

  1. Easy to Use – Geo Redundancy
  2. Robust API access
  3. Very Cheap storage space:

It costs about $0.03/ GB/ month- which is 6.5x less than SharePoint storage cost and

300x less than CRM storage cost.

Learn more about pricing here:

API Coding for CRUD Operations in Azure Blob:

I have written a sample plugin which will migrate the CRM attachment to Azure blob, and save the Azure blob file link back in CRM. The plugin is registered on Annotation entity

For this, I have used a RestHelper and BlobHelper utility code files, which have all the operations of (a) making a web request and (b) performing blob operations.

The Helper files and the CRM plugin sample can be found in the below GitHub link:

The plugin file is UploadDocumentToBlob.cs

  1. The below code from the plugin file takes the document from CRM and creates a blob using REST API:
 Entity entity = (Entity)context.InputParameters["Target"];

                string documentBlobURL = string.Empty;

              //// Optional condition to migrate attachments related to particular entity.

                //// If you want to migrate attachments for all entities, remove this CONDITION
                if (entity.Contains("isdocument") && entity.GetAttributeValue<bool>("isdocument") == true &&

                    entity.GetAttributeValue<string>("objecttypecode") == "account")


                    string storageAccount = "<storageaccountname>";

                    string filename = entity.GetAttributeValue<string>("filename");

                    string containerName = "<blobcontainername>";

                    string storageKey = "<blobstorage_accesskey>";

                    //// Read File

                    string text = entity.GetAttributeValue<string>("documentbody");


                    BlobHelper blobHelper = new BlobHelper(storageAccount, storageKey);

                    bool isUploadSuccess = blobHelper.PutBlob(containerName, filename, text);

                    //// Once blob upload is Success, get the Azure blob download-able URL of the uploaded File

                    if (isUploadSuccess)

                        documentBlobURL = string.Format("https://{0}{1}/{2}", storageAccount,

                            containerName, filename);


Let me know your suggestions on this blog, please use the comments for suggestions/ queries.

CRM TimeZone issue using JavaScript

Problem: When we try to save a datetime field from an HTML TextBox (date-picker)  to CRM using oData in JavaScript, the datetime is always saved incorrectly.

Why This happens:

  • In JavaScript, date object is always read in local timezone. But CRM always accepts date Object in UTC from any client application. Then it shows Date and Time in the TimeZone selected by the User for CRM environment.
  • So, when we send this data to CRM using oData, it assumes that the date is in UTC timezone and thus we see incorrect time in CRM views and forms for the record.
  • Also we cannot convert to required TimeZone in JavaScript. We can convert Date object to UTC using .ToUTC() method, but it returns a Date string instead of Date Object and we need Date object to pass to oData.
But Don’t you worry, we have found the resolution !! 🙂 

In our example, we were trying to create an appointment from a HTML Form using a custom datepicker for setting Start date of the Appointment record.



1. Read the local date in a string in JavaScript like below.

// textboxvalue = ‘2015/04/15 00:20’

var scheduledStart = new Date(textboxvalue + ‘ UTC’);

2. This will get the UTC date for the date specified. I am running the code from IST. So, the Scheduled Start will be :

“Thu Jan 15 2015 05:50:00 GMT+0530 (India Standard Time)”

3. When we pass this data to oData create/ update method, we will now see the correct date as expected. Below is the code to create an appointment using oData with required date conversions to see correct data

function createAppointment(currentAccount) {
“use strict”;
var appointment = new Object();
var scheduledStart = new Date(currentAccount.scheduledStart + ‘ UTC’);
var scheduledEnd = new Date(currentAccount.scheduledStart + ‘ UTC’);
scheduledEnd.setMinutes(scheduledStart.getMinutes() + 30);
appointment.Subject = “Sales Visit – ” + currentAccount[“Name”];
appointment.RegardingObjectId = { Id: currentAccount[“Id”], LogicalName: currentAccount.EntityName.toLowerCase(), Name: currentAccount[“Name”] };
appointment.ScheduledStart = scheduledStart;
appointment.ScheduledEnd = scheduledEnd;
var jsonEntity = window.JSON.stringify(appointment);
var createRecordReq = new XMLHttpRequest();
var ODataPath = Xrm.Page.context.getServerUrl() + “/XRMServices/2011/OrganizationData.svc”;‘POST’, ODataPath + “/” + ‘AppointmentSet’, false);
createRecordReq.setRequestHeader(“Accept”, “application/json”);
createRecordReq.setRequestHeader(“Content-Type”, “application/json; charset=utf-8”);
//Alert the Id of the created record


Hope this is helpful !!

The above resolution is successfully tested.. Please email/ comment if there is any other solution for this problem.

CRM Best Practices

This blog will have links of all the CRM Best Practices which means this will keep on updating as and when I find anything new or useful for CRM (read CRM Online)

  1. Workflow Wait Conditions: Best Practices-

  2. Open Modal Dialogs in CRM 2013 

  3. Attach Entity record notes/ attachment to Email in Custom Email Workflows

More links to follow. Keep watching this space.


Any suggestion for such links/ blogs will be great. You can add it in comments.