Tuesday 18 August 2015

Query office graph in Office Add-in using SharePoint search

I've been playing around with Office add-ins lately, so I decided to write a post about it.

In this example we are going to login to SharePoint using Office 365 APIs, as described by Richard diZerega in this blog post.

To authenticate, we will perform a manual OAuth flow, which was really well described by Chaks here.

Transcribing Richard's description on the authentication process:

"Here are the high-level steps for this flow and cross-window communication:
  1. Check for a user cookie (which maps to a refresh token in a database)
  2. If the user doesn't have a cookie…generate a new GUID and store as cookie
  3. Launch the OAuth flow with Azure AD in a new window (passing the GUID as reference)
  4. Use the authorization code returned from the OAuth flow to get access and refresh token
  5. Store the refresh token in the database with the GUID user reference
  6. Prompt the user to refresh the Office app (which can now lookup the refresh token by the GUID user reference that is stored in a cookie)
  7. Use the refresh token in the app to get resource-specific access tokens for data retrieval"
Here is the script that is launched for unknown users:


And here is the OAuthController for managing the authorization code response from Azure AD: 


To get the access token using the code retrieved by the authentication flow, the following code will be executed:


All the values must be defined in the web.config, as we're retrieving them using our 'SettingsHelper' class:



After the last action, a view will be retrieved, informing the user to close the prompted dialog. Nothing new till now, all of this was already described by Richard.

Since we're authenticated now, let's start building our File's class to store the values we need:


Now we can create our FileRepository class, to implement the method to get the files from SharePoint using search API...


Our 'GetFiles' method will receive a token and a parameter which will indicate what do I want to retrieve. In order to summarize, I will explain the "My Work" query:

query = "/search/query?Querytext='*'&Properties='GraphQuery:AND(ACTOR(391380\\,action\\:1003)\\,ACTOR(391380\\,OR(action\\:1003\\,action\\:1036\\,action\\:1037\\,action\\:1039)))'&selectproperties='Title,Path,ViewsLifeTime,LastModifiedTime,SiteID,WebId,UniqueId,SecondaryFileExtension,SiteTitle,SPWebUrl,ServerRedirectedURL,EditorOWSUSER'";


  • /search/query?Querytext='*' - We're using the search api and defining the text as '*', which is any text.
  • &Properties='GraphQuery:AND(ACTOR(391380\\,action\\:1003)\\,ACTOR(391380\\,OR(action\\:1003\\,action\\:1036\\,action\\:1037\\,action\\:1039))) - Here we're saying that we want to specify properties of a graph query (using actor(s) and action(s)). In this example I'm using my own Actor ID "391380", since we're getting access using app permissions, it won't work if I define the actor as "ME".
  • &selectproperties='Title,Path,ViewsLifeTime(...) - finally, let's bring the properties we need (specified in the File class).
After our request being processed, we'll store the response relevant information:



With all the business logic done, let's talk about controllers and views...

Controller:

Our controller will get the stored token and get the files using the token and a parameter to indicate that I want "My Work" files (Created and/or modified by me)


View:

Let's call the Index action in our view with a fancy button...


Aaand it's done! A little bit of creativity and you can, for example, to have Delve in an Office add-in:



Happy coding!