A better SharePoint Connector – part 6: The SharePoint class library is born!

It has been a quite rough ride, SharePoint turned out to be a relative of the Lernaean Hydra. Each time you thought you defeated her, a new head popped up and the battle started all over again. I finally know what Heracles must have felt once he defeated the hydra for once and for all.

527px-Singer_Sargent,_John_-_Hercules_-_1921

As I mentioned in the previous article, I had some unfinished business:

  • Set the meta data of the list item attached
  • Implement a file exist check

Implementing the file exist check was a pretty straight forward task.  

The SharePoint REST API provides the _api/web/getfilebyserverrelativeurl(‘<relative url>’)/<property name>  function call. One of the properties you can query is the “Exists” property (see MSDN).
In case the file exists the result of the REST call is a JSON string containing a true value. If the file exists you have to rename the file (as otherwise existing files in the document library get overwritten. In our case I’ll insert a timestamp inside the file name containing the date and time. The result of the check is either the original file name or the timestamped file name.
In case the file does not exist, the REST call raises an exception which will be handled.

In the previous article I wrote about the steps involved to set the meta data on the newly added document.

  • Execute the ListItemAllFields, to get detailed information about the list item attached to the document
  • Extract the information from the ListItemAllFields JSON results to do the actual update.

To be able to do the update on the list item, the following information is needed (see ListItemAllFields JSON result below):

{"d":{"__metadata":{"id":"Web/Lists(guid'0ceeae1d-e6cc-4699-bc6c-0e1f1e7e0974')/Items(8)",

"uri":"http://dev-bvdsande:8080/_api/Web/Lists(guid'0ceeae1d-e6cc-4699-bc6c-0e1f1e7e0974')/Items(8)",

"etag":"\"1\"",

"type":"SP.Data.Shared_x0020_DocumentsItem"},

"FirstUniqueAncestorSecurableObject":{"__deferred":{"uri":"http://dev-bvdsande:8080/_api/Web/Lists(guid'0ceeae1d-e6cc-4699-bc6c-0e1f1e7e0974')/Items(8)/FirstUniqueAncestorSecurableObject"}},
"RoleAssignments":{"__deferred":{"uri":"http://dev-bvdsande:8080/_api/Web/Lists(guid'0ceeae1d-e6cc-4699-bc6c-0e1f1e7e0974')/Items(8)/RoleAssignments"}},
"AttachmentFiles":{"__deferred":{"uri":"http://dev-bvdsande:8080/_api/Web/Lists(guid'0ceeae1d-e6cc-4699-bc6c-0e1f1e7e0974')/Items(8)/AttachmentFiles"}},
"ContentType":{"__deferred":{"uri":"http://dev-bvdsande:8080/_api/Web/Lists(guid'0ceeae1d-e6cc-4699-bc6c-0e1f1e7e0974')/Items(8)/ContentType"}},
"FieldValuesAsHtml":{"__deferred":{"uri":"http://dev-bvdsande:8080/_api/Web/Lists(guid'0ceeae1d-e6cc-4699-bc6c-0e1f1e7e0974')/Items(8)/FieldValuesAsHtml"}},
"FieldValuesAsText":{"__deferred":{"uri":"http://dev-bvdsande:8080/_api/Web/Lists(guid'0ceeae1d-e6cc-4699-bc6c-0e1f1e7e0974')/Items(8)/FieldValuesAsText"}},
"FieldValuesForEdit":{"__deferred":{"uri":"http://dev-bvdsande:8080/_api/Web/Lists(guid'0ceeae1d-e6cc-4699-bc6c-0e1f1e7e0974')/Items(8)/FieldValuesForEdit"}},
"File":{"__deferred":{"uri":"http://dev-bvdsande:8080/_api/Web/Lists(guid'0ceeae1d-e6cc-4699-bc6c-0e1f1e7e0974')/Items(8)/File"}},
"Folder":{"__deferred":{"uri":"http://dev-bvdsande:8080/_api/Web/Lists(guid'0ceeae1d-e6cc-4699-bc6c-0e1f1e7e0974')/Items(8)/Folder"}},
"ParentList":{"__deferred":{"uri":"http://dev-bvdsande:8080/_api/Web/Lists(guid'0ceeae1d-e6cc-4699-bc6c-0e1f1e7e0974')/Items(8)/ParentList"}},
"FileSystemObjectType":0,
"Id":8,
"ContentTypeId":"0x010100851EE10E271C4A4EA705D85000D5FC69",

"Title":null,
"Description0":null,
"SomeNumber":null,
"MoreText":null,
"MyChoice":"Keuze 1",

"ID":8,
"Created":"2015-01-13T22:22:43",
"AuthorId":1073741823,
"Modified":"2015-01-13T22:22:43",
"EditorId":1073741823,
"OData__CopySource":null,
"CheckoutUserId":null,
"OData__UIVersionString":"1.0",
"GUID":"191aafb5-3f8a-46e8-af76-f200f288480d"}}

In line 3 you find the “uri”, that is going to be used to post the data. Line 7 contains the type we have to send (otherwise the update will fail). Lines 23 to 27 contain the internal field names of the fields that can be set.

The values that are going to be set in SharePoint, are transformed into a JSON string and then passed to the REST call (POST method) using the URI specified in line 3. Furthermore the REST call needs some additional headers in order to MERGE the JSON send in with the existing record. The slightest mistake in the JSON string passed in will result in a nice HTTP 400,412 or 500 error.

Oops

The JSON string that needs to be build up contains the type of line 7 and one of more fields of lines 23 to 27. Eventually the JSON will look like this:

{‘__metadata’: {‘type’:’SP.Data.Shared_x0020_DocumentsItem’}, ‘MoreText’:’my random text’,’Description0′:’some description’,’SomeNumber’:13,’MyChoice’:’Keuze 3′}

This particular JSON string used to be Hydra’s final head. The monster has been defeated for once and for all. Heracles has been sent back to Greece.

For your convience I added the File Attachment: SharePointConnector.zip (10 KB) containing the helper classes and the SharePoint connector class.

Adding a file using the SharePoint connector is a breeze

byte[] data = File.ReadAllBytes(@"C:\development\testsolution.zip");

// set the site Url
string siteUrl = "http://dev-bvdsande:8080";
string docLib = "http://dev-bvdsande:8080/shared documents";

// Connect to the local environment
SharePointConnector cls = new SharePointConnector(siteUrl);

// build the dictionary to pass the values to be stored inside the list item
Dictionary<string, object> dict = new Dictionary<string, object>();
dict.Add("MoreText", "Meertekst");
dict.Add("Description0", "omscjhrijving");
dict.Add("SomeNumber", 13);
dict.Add("MyChoice", "Keuze 3");

// add the file to SharePoint, return the unique name
string url = cls.AddFile("test.zip", docLib, data,dict);

The next and final article in this serie of articles will describe the embedding of the SharePoint connector into CRM.

2 thoughts on “A better SharePoint Connector – part 6: The SharePoint class library is born!

  1. Sagar says:

    Hi.

    I am trying to create a sharePoint subfolder in sharepoint from the record created in CRM Online. At the moment, my code is able to create a document location in CRM but I am final aim to create a sharepoint subfolder inside the folder that is manually created from CRM.
    Is there a specific method or code inorder to achieve this? I have followed sample code from http://develop1.net/public/post/SharePoint-Integration-Reloaded-e28093-Part-3.aspx which is very helpful but unable to crack the final goal that i am looking for.

    Someone with really good understanding of CRM Online and sharepoint Online integration would be of great help. Eagerly waiting for your reply.

    Note: Using CRM and Sharepoint Online instead of on-premises products as they require specific dll’s inorder for code to work. Dll’s doesn’t work for Online products. Please help me out!

    Thanks,
    SD_Dev

    • Hi Sagar,

      if you use my libraries you can use CRM online as well, as I don’t use the SharePoint dll’s but purely trust on REST API to communicate with SharePoint.

      Bas

Leave a Reply

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