Document integration – part 2: Designing the concept

In my last article I described the flaws in the default SharePoint document integration; the use of folders instead of meta data, the flaky document retrieval capabilities and the lack of communication between the development groups within Microsoft (otherwise we would have had a rock solid integration between the products). I decided to do it myself…


I decided to design and eventually develop a flexible document integration. A solution in which I can store my documents in all kinds of document storages. In the proof of concept I’m going to develop, will store the documents to a webservice (that will save the document to a file share).
On the other hand the documents can be stored anywhere (as long as you write the correct provider for it). 

Technical concept

In it’s basis the technical concept is pretty straight forward. Below I drew a sketch in which I’ll explain how I envision the technical part of the document integration solution. In the first sketch I focus on getting the document into the storage location.
In the second sketch I’ll focus on retrieving the document or list of documents from the storage location.

In the sketch I distinguish a CRM client context and a CRM server context.
The CRM client context is the web context in which the user is working. The client context is based on HTML and Javascript.
The CRM server context is the part behind the scenes; the managed .NET code running inside a sandbox process.


The idea is simple, in a webpage inside CRM we create a javascript upload function. Using this function, we can transfer the document to the Dynamics Server. Once the document is uploaded, the uploaded document is offered to a custom action. An action is some sort of entity on which we can define incoming and outgoing parameters.
The advantage of posting the document to an action, is that we can use the action to enter the CRM server context. We do this by writing a plugin that is registered to handle the execute message registered on the action.

Given the input parameters of the entity we are able to get the file data and all meta data we need to store the document. Using that data we use the provider we configured in CRM, we store the document on it’s target location using the appropriate provider.
Once the document is stored we store the document location for the specific entity in CRM.


The principle behind retrieving documents from the external storage is almost the same. We send a message to the custom action in which we want to retrieve a list of documents for an entity name and a specific entity id.

Based on those settings, the plugin behind the action gets the document location.

Using the document location, the configured provider is executed: Giving either a list of documents (names + meta data only) or just the contents of a single docment (bytes, file name).

The action passes the data back to the CRM client context using its output parameters.  The client context renders the webpage with either download links (javascript to execute an action) or a javascript that streams the contents of the file as a binary stream to the browser. Forcing an open/save dialog in the browser.

Please hang on for a little moment, we have some unfinished business, e.g. code for implementing the various providers…

Input for the providers

Doing some research, I found some fancy .Net projects that I can use to write the various providers:

Furthermore we have to determine what methods the providers should support. Right now I envision the following methods:

  • byte[] Load(string entityName, Guid objectId, string name)
    Load a single document given the entityName, objectId and the name of the document. The function returns a byte array containing the document data.
  • List<document> LoadList(string entityName, Guid objectId)
    Loads a list of documents given the entityName and the objectId. The function returns the name of the documents and related metadata,
  • string Save(string entityName, Guid objectId, string name)
    Saves the document in the storage location using the entityName and objectId to identity to what specific entity instance the document is related to using the name to identity the document.
    In case the name exists, a unique name is generated. The unique name under which the document is saved is returned for further processing.

These methods form the basis of the interface we use for our provider. Additional methods will be added to the signature if needed.

More to come, in the next article.

* phew…. enough techno babble for one evening, time for a beer *