Integrating CRM Online and SharePoint Online: I need a hammer!

Last week I have been working on a project in which I had to integrate SharePoint Online within CRM Online. I was excited because I had to enrich data in CRM with data stored in SharePoint. Both running on line :)
When I started I thought that it was going to be a fairly simple job, as Microsoft provides the Microsoft.SharePoint.Client dlls. At first I built a console application in which I would receive the data from SharePoint.

SecureString securePassword = new SecureString();
foreach (char c in password.ToCharArray()) securePassword.AppendChar(c);

SharePointOnlineCredentials credentials =  new SharePointOnlineCredentials(userName, securePassword);
ClientOM.ClientContext context = new ClientOM.ClientContext(siteUrl);

context.Credentials = credentials;

ClientOM.Web web = context.Web;
context.Load(web);
ClientOM.List lst = web.Lists.GetByTitle(listName);
context.Load(lst);
... and so on ...

I wrote the logic, tested it, embedded it inside the CRM plugin, deployed it to CRM online and I was good to go… 

All hell broke loose

As soon as I started to test my plugin, all hell broke loose. CRM crashed so badly that even the exception handling I implemented wasn’t triggered! This can only be caused by low level calls (probably in underlying COM functionality). NASTY!
The plugin actually crashed on the very first SharePoint related statement setting the “SharePointOnlineCredentials” object. Nothing fancy one would say.
I ran into a solid wall. If I couldn’t use the client side object model, how do I had to get my data?

REST to the rescue

After doing some research, it turned out that REST was the way to go. Using rest means that I’m not dependant on the SharePoint client dlls, it also means that I have to do the plumbing myself. During my research I stumbles upon some C# classes built bij SharePoint developers to facilitate the REST operations on SharePoint. This included authentication as well. I had to make a couple of small modifications to let the functionality land on the sandbox of CRM online.

In the File Attachment: SharePointHelpers.zip (7 KB), you’ll find the modified classes. You can use the classes by making the following call.

Uri spSite = new Uri(siteUrl);

bool success = SpoAuthUtility.Create(spSite, userEmailAddress, WebUtility.HtmlEncode(password), false);

if (success)
{
Uri url = new Uri(String.Format("{0}/{1}", SpoAuthUtility.Current.SiteUrl, restQuery));
Dictionary<string,string> headers = new Dictionary<string,string>();
headers.Add("binaryStringResponseBody","true");

// Send a json odata request to SPO rest services to fetch all list items for the list.
byte[] result = HttpHelper.SendODataJsonRequest(
url,
"GET", // reading data from SP through the rest api usually uses the GET verb
null,
(HttpWebRequest)HttpWebRequest.Create(url),
SpoAuthUtility.Current, // pass in the helper object that allows us to make authenticated calls to SPO rest services
headers // specify that sharepoint needs to return uncontaminated bytes....
);

string response = Encoding.UTF8.GetString(result, 0, result.Length);
Console.WriteLine(response);
}

Finally I tackled the problem, but… some days you really wish you had a big hammer!