Wednesday, December 3, 2014

Upload file in SharePoint online document library (folder) with REST and active authentication.

In this post I'll explain you what I did to upload a local file into a SharePoint Online Office 365 document library. The second step in this example is providing the new document with a proper value for the title meta data field.
This example is a console application written in C#, not using the Microsoft.SharePoint.Client.dll but only making calls to REST endpoints.
A CRM developer asked me to write this piece of code so he could implement this logic into a custom CRM module, that module had to copy a file from CRM online to SharePoint online.

When the application is launched the console will ask you for some parameters:
  • path of the file to upload
  • title for the new document 
  • document library name
  • folder name (in this example, I expect a folder)
  • site collection URL (in this example, sub sites are not taken into account)
  • O365 user name
  • password
As you see, the application will ask for a user name and password. These credentials are used to authenticate the application with SharePoint. I've used the authentication mechanism build by Wictor Wilén. If you're interested in this authentication mechanism you definitely should read his post.

This console app is just an example on how we can upload a document. The SharePoint document library and the folder must exist, the code won't create them for you. If they don't exist, the code will throw a 404 exception.

If everything goes well, you should see something like this:



Where the magic happens

The download link is available at the end of this article. Download and adapt for your needs.

As explained earlier the application exists of 3 blocks
  1. authentication -> get security token by calling STS of Office 365. This security token is sent to SharePoint, if SharePoint accepts it will return 2 cookies. Those cookies we have to include in each (REST) request we do to SharePoint.
  2. Reading the local file as a byte array and uploading the file in the correct folder.
  3. When the upload is succesfull, we give the Title metadata field a proper value.

Reading and uploading the file with REST (c#)

Following code snippets are only there for explaination reasons, download the full example to get a working application.

When authentication is succesfull and we have the 2 required cookies in our container, I have to obtain the formdigest, this digest is mandatory if your REST call is writing data to SharePoint. We will inlcude this formdigest as property X-RequestDigest in the header of the request. The binaryStringRequestBody property is the second one we add in the header. This property is mandatory because we will upload a document as a byte array.
When preparations are done we can actually do the webrequest by calling HttpHelper.SendODataJsonRequest. After including the cookies, this function will call SendHttpRequest() where the actual request is done. Properties of the request:

  • request.Method = "POST"
  • request.Accept = "application/json;odata=verbose"
  • request.UserAgent = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)"; //must be there, otherwise http 403 error
  • request.AllowAutoRedirect = false; // This is key, otherwise it will redirect to failed login SP page
  • request.Headers
    • binaryStringRequestBody: true
    • X-RequestDigest: [value of formDigist]
  • request.ContentType = "application/json;odata=verbose"
  • request.ContentLength = requestContent.Length;
  • request.GetRequestStream() -> read byte array of file.


Changing Title metadata field of the fresh document.

Second step is to give the new document a proper title. In fact the process is very similar to the upload of the document. Here a list of the differences:

  • body: instead of processing the byte array of the document, now the body of the request will contain a string in which we define the changes to the metadata.
  • headers: since we are doing again a POST request, the X-RequestDigest is again required for security reasons. 2 other properties are required as well:
    • X-HTTP-Method = MERGE
    • IF-MATCH = *
The MERGE method updates only the properties of the entity that you specify.

Here you can download the Visual Studio Project.

**UPDATE: Since System.Web.Extensions is not available in a CRM sandboxed solution, json deserialization is done with System.Runtime.Serialization.Json. Thanks to Kris for helping me out.


7 comments:

  1. Hi nice blog but i can not find the visual studio project

    ReplyDelete
    Replies
    1. You're right, must have accidentally deleted it. I'll check if I can upload it again.

      Delete
  2. DO you still have this VS File available? It doesn't seem to be in the OneNote link.

    ReplyDelete
  3. This comment has been removed by the author.

    ReplyDelete
  4. Hi Sander,

    I have a similar requirement. I am not seeing the project in the link. Could you please email the project solution to kar.ayush@gmail.com

    ReplyDelete