Friday, 8 May 2015

Using the Office 365 Unified API in ASP.NET MVC

In my previous post, I wrote about Getting started with the Office 365 Unified API. In that post, I introduced the new Office 365 Unified API and created a basic console application which used Azure AD for authentication and consumed the Office 365 Unified API. But chances are that a console application is not going to be a solution to most of your business needs. That is why, in this post we will see how the Office 365 Unified API can be used in an ASP.NET MVC application.

The complete code for this blog post is available on GitHub: https://github.com/vman/O365UnifiedAPIMVC

Full credit to Jason Johnston's article Getting Started with the Outlook Mail API and ASP.NET on which I have based my code.

The Authentication flow:


Since the Office 365 Unified API uses Azure AD for authentication, these are the basic steps to get your application authenticated:

1) Request an authorization code

2) Request an access token based on the authorization code. (when you successfully make this request, you also get back the refresh token along with the access token)

3) Make a request to the desired resource e.g. "https://graph.microsoft.com/beta/myOrganization/users" using the access token.

4) When the access token expires, use the refresh token to get a new access token instead of going through the entire authentication flow again.

See the following links for more details on the Office 365 Unified API and the Azure AD authentication flow:

Authorization Code Grant Flow

Office 365 Unified REST API authentication flow

Register your application in Azure AD:


Now let's get started on how to actually go through this process in an MVC application.

As mentioned in my previous post, the very first thing you need to do is register your application in Azure AD. Here are the steps to do that:

https://msdn.microsoft.com/office/office365/HowTo/get-started-with-office-365-unified-api#msg_register_app

I have registered a Web Application in this case and here are the permissions I have granted:


Windows Azure Active Directory:
  • Access your Organization's Directory

Office 365 unified API (preview): 
  • Read and write all users' full profiles
  • Access directory as the signed in user
  • Enable sign-in and read user profile

If the Office 365 unified API (preview) application is not available by default, click on "add application" and add it.

After you register your application, copy the ClientID and the ClientSecret in the web.config file of your MVC application.

<configuration>
  <appSettings>
    <add key="ida:ClientID" value="your client id" />
    <add key="ida:ClientSecret" value="your client secret" />
  </appSettings>
</configuration>

Now that the application is successfully registered in Azure AD, we can go ahead and write the code for the authentication flow in our MVC app.

The ASP.NET MVC Application:


The first thing you need to do now is to get the following NuGet package installed in your project:

Active Directory Authentication Library 2.14.201151115

Alright, we are finally ready to write some code now :)

In your MVC Controller, create an action called SignIn. We will use this action to redirect the application to the Azure AD Authorization Request Url:



This will take the application to the Azure AD login page where the user will have to enter his/her credentials. Once the credentials are successfully authenticated, the application will be taken to the redirectUrl mentioned in the code. This redirectUrl is a url to another Action in our MVC app. At this time, the url will also contain the Authorization code mentioned in step 1 and 2 above.

The Authorize action mentioned in the redirectUrl looks like this:



This will get the Authentication code from the request parameters. Based on the Authentication code, it will make a call to Azure AD to get the Access token. Once we get the Access token, we will store it in the session so that we can use it for multiple requests.

A production level solution will probably need a better mechanism to store the Access token. Andrew Connell has written a great article on storing the access token in a database. See the article here:

Azure AD & ASP.NET MVC - Walk-Through Implementing ADAL & OWIN

Now that we have a valid Access token, we are ready to actually make a call to the Office 365 Unified API resource to get data. I have used a simple HttpClient to make the REST call

Once the call is successful, you get JSON back which then you are free to mangle in your code.



In my sample application, I have also written calls for getting all the users from the tenant and the tenant details. Check it out here: https://github.com/vman/O365UnifiedAPIMVC

Additional Reading/Fiddling:


Here is the complete list of REST calls you can currently make using the Office 365 Unified API:

Office 365 unified API reference (preview)

Also, if you want to try out REST API without actually writing any code, this is a great tool which can help you make calls and see the response: http://graphexplorer2.azurewebsites.net/

Only thing is you will need credentials to install the application in your Azure Tenant.

Hope you found this post useful!

Monday, 4 May 2015

Getting started with the Office 365 Unified API

The Office 365 Unified API was recently launched at Build 2015. It uses Azure AD for authentication and has just one endpoint "graph.microsoft.com" which can be used to query for data from any service across Office 365.

This is a very important thing according to me because in the earlier versions of this API we had to query a discovery service and get the URL of the individual service (SharePoint, Outlook, Azure AD etc.) from which we wanted to get the data.  With the new unified endpoint, it becomes easier for us Developers to just query a single endpoint for data from any of the services across Office 365.

Complete information about the Office 365 Unified API can be found here: https://msdn.microsoft.com/office/office365/HowTo/get-started-with-office-365-unified-api

I decided to try my hand at the .NET Client Library of the Office 365 Unified API. Here is the complete code for my console application: https://github.com/vman/Office365UnifiedConsoleApp

1) The very first thing you will need to do is register your application in Azure AD and get the client id. You can think of this as being somewhat similar to registering an App Principal for a SharePoint App (Add-In as it's now called).


For my test app, I have registered a Native Application (as opposed to a Web Application) mostly because the process for a native application is a bit simpler. For a Web Application, you also need a client secret along with the client id. I decided to keep things simple for my first console app.

2) When you register your app to Azure AD, do not forget to grant the appropriate permissions in the "permissions to other applications" 

3) Make a note of your client Id. You will require this in your code:

4) Create a new Console Application Project in Visual Studio and add the following NuGet packages to it:

Active Directory Authentication Library 2.14.201151115

Office 365 unified API client library (preview) 0.2.6-rc

5) Now you are set up to write code against the Office 365 Unified API.

The very first thing you will need to do is get the access token from Azure AD. Once you have the access token,  all you need to do is create an object of the GraphService class and use it to get data from Office 365 provided you have the right permissions set up in Azure AD.

Here is my sample console application code:



Once you run this code, you will get a prompt to enter your Office 365 credentials:


Once you enter the right credentials, the access token will be fetched and passed on to the GraphService client object which will then use it to get the current user from the GraphService.Me property and display it on the console.

Hope you enjoyed reading this as much as I enjoyed fiddling around with this new API :)


Sunday, 26 April 2015

Add a Site Collection administrator to all Site Collections in a Tenant

I have come across this scenario many times where even if I am the tenant admin in my SharePoint Online tenant, it is not necessary that I will be the site collection admin of every site collection by default. This is by design and makes perfect sense as there might be some site collections where sensitive data might be stored and I might not have rights to see that data despite being the tenant admin. However, in some scenarios you might feel the need to give a user site collection admin rights for all the site collections in the tenant.

Also for OneDrive for Business site collections in the tenant, the user who is owner of the site collection is the only person who has site collection admin rights on it by default. This can be a problem for compliance and e-discovery reasons. You might be in a situation where you need to give site collection admin rights to a compliance manager or a global administrator on all the user's OneDrive for Business sites.

In this post, lets have a look at how you can make a user a site collection admin on all the site collections in a tenant as well as on all the OneDrive for Business site collections in the tenant.

Some notes:

1) For now, this only works with SharePoint Online/Office 365.
2) You will need the SharePoint Online Client Side Object Model Nuget package
3) By changing a parameter in the SetSiteAdmin function, you can also remove a user from the site collection admins of all site collections.
4) The user who runs this code will need Tenant Administrator rights on the Tenant.

1) Add a site collection admin to all site collections in a tenant:


This is the easy part, all you need to do it get the urls of the site collections in the tenant and add the desired user as a site collection admin to it using the Tenant.SetSiteAdmin function.


2) Add a site collection admin to all the OneDrive for Business site collections in a tenant:


This takes a bit more work. Here are all the things we need to do:

1) Get the account names of the users in a tenant using People Search. Now bear in mind that search has a limitation of returning a maximum of 500 rows on SharePoint Online. That will be 500 users in our case. So if your tenant as more than 500 users, you will need to call search in batches of 500 to get the account names of all the users.

2) Once we have the account names of the users, we need to get the url of their OneDrive for Business sites. We can do this by querying the CSOM UserProfile API

3) After getting the OneDrive for Business site urls, all we need to do is use the same Tenant.SetSiteAdmin function as above.

Here is the complete code for that:


There is also another way to do the same thing where you get the OneDrive for Business site urls from the UserProfileService.asmx and then use the Set-SPOUser SharePoint Online PowerShell cmdlet to set the user as the site collection admin. Here are the details for that https://technet.microsoft.com/en-us/library/dn765092.aspx

Hope you found this article useful!

Wednesday, 25 March 2015

CSOM tip for making your code flexible

We all know that in CSOM, for any given object, we can specify certain properties to be brought back from the server. Something like this:

This will only bring back the Title property of the web thus reducing data traveling over the wire.

Now in this case, the second parameter of the clientContext.Load method is an object of type Expression<Func<Web, object>>[]

This is an array of Linq expressions which can be utilized to our benefit. We can convert that array into a parameter which can be passed to a "Utility" function. This function will only get the properties specified in that array. Like this:

Then, that function can be called with different parameters depending on the properties we want to fetch from the server for that particular instance. For example:

Only get the Title and Id of the Web:

Only get the MasterUrl and the CustomMasterUrl of the web:

For both the above calls, we are not changing the GetWebDetails function. It will always return a Web object with the specified properties filled in. It will also reduce data travelling over the wire, as only the specified properties will be fetched. Thus, making your code more flexible and performance friendly.

You can also have other utility functions for Lists, Users etc. Here is a similar function for Lists:

Hope you find this useful!

Monday, 23 March 2015

Custom Taxonomy Picker for Provider Hosted Apps

When working with SharePoint Online or developing cloud friendly solutions, it can be tricky to replicate some functionality which is easily available on-premises. We had a scenario recently where the user should be able to set values for a Managed Metadata user profile property. Now if this was a farm solution, we could have used a variety of methods like User Controls, Taxonomy Pickers etc. But since this was a Provider Hosted App, all those options were not available to us.

I knew that the Office Dev Patterns and Practices project has a cloud friendly taxonomy picker but that did not fit our requirements. It requires the creation of an App web in which sense it is not a "pure" provider hosted app. Also, there were some specific requirements around styling and business logic which meant that a custom Taxonomy Picker was the only way forward.

GitHub link for this project:
https://github.com/vman/CustomTaxonomyPicker

So without much further ado, here is how the custom User Profile property taxonomy picker looks:

1) When loaded first on a page, it gets the values from the "Skills" user profile property and displays them as tags:



2) When you start typing into the input box, the auto-complete suggestions are based on the "Keywords" termset. (You can change this to get terms from another termset)



3) When you are happy with the values, click on update and your Skills user profile property will be updated with the selected values:



And that's basically how it works from an end user perspective.

Advantages:


1)  Pure provider hosted app. No App web required.  If you are on-prem and in a big enterprise, this means that you don't have to wait for a wild card DNS entry to be setup. We all know how long that can take. This can be implemented as a pure provider hosted app because all calls to SharePoint are made by using CSOM in an MVC controller.

2) Complete control. Can be customized anyway you want. If you have specific business logic which needs to manipulate data before sending it to SharePoint, then you are easily able to do so.

3) Customisable UI: The jQuery Tag-It plugin is used in this taxonomy picker. It supports jQuery ui themes and a whole lot of other styling options. More about this in the Technical details section below.

Limitations:


1) As is, this control only works with SharePoint Online/Office 365. This is because the API for writing user profile properties is not yet available for SharePoint On-Premises. But if you are up for it, you can use the UserProfileService.asmx for accomplishing the same functionality. Check out this sample to see how to do it:
https://github.com/OfficeDev/PnP/tree/master/Samples/Core.UserProfilePropertyUpdater

2) At this time, it can only be used with user profile properties. If this has to work with Taxonomy fields in a list, you will have to modify the code but the principles behind the approach would stay the same.

But hey, the source is on GitHub so you don't get to complain! Submit a pull request and I will be happy to merge it :)

Technical Details:


1) Permissions:


Since the app interacts with the Managed Metadata Service and writes to the User Profile Service, the following permissions are needed:




2) jQuery Tag-It plugin:


The completely awesome jQuery Tag-It plugin is used to present the terms as tags in the UI. It provides a wide variety of options for selecting tags. It accepts a JavaScript array of values to show auto-complete suggestions.  Check out the plugin home page for more details.

3) Get current user's skills:


When the page loads, we need to get the skills for the current user to show them by default in the control, this can be done by making a simple call to the UserProfile Service.



4) Get terms from the Keywords termset:


To show the auto-complete suggestions, the Tag-It plugin requires a JavaScript array of values. We will use a MVC controller to get the keywords from the Managed Metadata Service and pass the values as a JavaScript array to the plugin. You can use any other termset to get your values. It would also be a good idea to cache these values in the browser localStorage so you don't have to make a call to the Managed Metadata service every time the control loads.



5) Update current user's skills:

When the Update button is clicked, another call is made to the Skills MVC controller which uses the recently released user profile write methods from CSOM. More about them on Vesa Juvonen's blog:
http://blogs.msdn.com/b/vesku/archive/2014/11/07/sharepoint-user-profile-properties-now-writable-with-csom.aspx

If you are on-premises, you can still use the UserProfileService.asmx for that. See this Office Dev PnP sample:
https://github.com/OfficeDev/PnP/tree/master/Samples/Core.UserProfilePropertyUpdater

Thanks for reading! Hope you found this useful.

Wednesday, 28 January 2015

Set user profile properties using JSOM & JavaScript

User Profile properties were recently made writable from the CSOM. Vesa Juvonen has a great post about it here . In addition to that, I have also blogged about how a Tenant admin can set the user profile properties of the users in the tenant.

In this post, I will show you how to set the current user's profile properties using the JavaScript Client Object Model (JSOM). Please refer to the 2 posts I have mentioned for any additional details around this.

Right now this functionality is only available in SharePoint Online/Office 365. If you want this functionality to come to SharePoint 2013 On-Premises, please create or up-vote on the feedback here: https://officespdev.uservoice.com/

Saturday, 24 January 2015

Glimpse of the upcoming Office 365 Video API

Update (21/04/2015): Here is the preview of the Office 365 Video API: https://msdn.microsoft.com/office/office365/APi/video-rest-operations

--------------------------------------------X--------------------------------------------------

A while ago, I wrote a post about getting all the video channels and videos from the Office 365 Video Service.  Shortly after that I got a word from Microsoft that there is going to be a public API for accessing Office 365 Videos. I was allowed to share the information as long as I mentioned that the API is not documented yet and is still being worked upon. So there is a possibility that it might change in the future so it is advised that this should not be used in production until it is fully stable and documented.

Here is how the API will work:

1) Get the right path from the discover endpoint:


https://site.sharepoint.com/sites/team/_api/VideoService.discover

The returned JSON will contain the following values among others:

{
    "IsVideoPortalEnabled": true,
    "VideoPortalUrl": "https://site.sharepoint.com/portals/hub"
}

IsVideoPortalEnabled will be true if your tenant has got Office 365 Video and VideoPortalUrl is the url which we will use to make further REST calls.

2) Get all Video channels with the VideoPortalUrl:


https://site.sharepoint.com/portals/hub/_api/VideoService/Channels

The returned JSON will contain all the channels with their unique GUIDs:

{
            "Description": "",
            "Id": "eaa748d7-97d6-43f1-8780-ce5c8acbf2bb",
            "TileHtmlColor": "#0072c6",
            "Title": "Development"
}

3) Get all videos from a single video channel:


Here, we will use the Id obtained from the previous call to get all the videos from a particular channel:

https://site.sharepoint.com/portals/hub/_api/VideoService/Channels('eaa748d7-97d6-43f1-8780-ce5c8acbf2bb')/Videos