Serverless — Azure Function API using CSOM

Sumit Agrawal
ng-sp
Published in
5 min readMay 26, 2018

Previously, we had build an Azure Function that uses CSOM to connect with SharePoint Online. Let’s build an API that will return data.

Create Azure Function

Similar to the function that we had build in last post, create a new Function and add project.json file with below mentioned content. This nuget package by PnP is the only package that we need to connect with SharePoint Online.

{
"frameworks": {
"net46": {
"dependencies": {
"SharePointPnPCoreOnline": "2.15.1705"
}
}
}
}

One you save this file, Azure Function will start restoring this package and this will be available to us for use in our function.

At the top of the function in run.csx, declare below using statements.

#r "Newtonsoft.Json"
using System.Net;
using OfficeDevPnP.Core;
using Microsoft.SharePoint.Client;
using Microsoft.Online.SharePoint.TenantAdministration;
using Microsoft.Online.SharePoint.TenantManagement;
using Newtonsoft.Json;

Note how we are referencing Newtonsoft.Json assembly.For framework assemblies, we have to add references by using the #r “AssemblyName” directive. We intend to use Newtonsoft.Json so that we can return responses in JSON format. Now let’s add some configurations that we will need to use.

Adding configuration data for Azure Function

To add configuration data that your function can use, Go to your Azure App instance, and you will see multiple tabs, navigate to Application settings under Platform features tab. This is the area where you will store all the configuration data.

For our purpose, we will connect with our tenant and fetch some data based on site url. Declare below 3 configuration values:
tenantUrl — https://tenantName-admin.sharepoint.com clientId — clientId that has full control at tenant level. clientSecret -secret generated along with client Id.

To grant tenant level full control access to app, navigate to https://tenantName-admin.sharepoint.com/_layouts/appinv.aspx page and grant below permission xml to this client Id:

<AppPermissionRequests AllowAppOnlyPolicy="true">  
<AppPermissionRequest Scope="http://sharepoint/content/tenant"
Right="FullControl" />
</AppPermissionRequests>

AllowAppOnlyPolicy specifies that this app can make calls to SharePoint without a user’s context.

Now we have Id and secret ready that can be used for accessing our Tenant. Configure these settings in Application settings of Azure Function as below:

To read these key value pairs from Azure Function, we will use GetEnvironmentVariable() method that is available to us:

String result = System.Environment  
.GetEnvironmentVariable(key, EnvironmentVariableTarget.Process);

Enable CORS

Next step is to enable CORS. To protect our Azure Function from calls from malicious origins, by default function will reject calls from any domains. If you see CORS settings, by default only Azure Function domains are registered. You should only register domains from where you intend to call this Azure Function. In our case it is our SharePoint Online tenant. We will register this tenant. This completes our configuration section. Now we will see how we can check site quota for a particular site collection using our Azure Function API.

Validate Query String paramters

To check for site quota, we will be requesting url of site collection to be passed as a query string parameter to our Azure Function. Below code will check for existence of query string parameter named urland will return response as a bad request if this parameter is missing.
We are returning status code 400 using HttpStatusCode.BadRequest when this query string parameter is missing from Azure Function call.

public static async Task<object> Run (HttpRequestMessage req, TraceWriter log) {  
// check that query string value is passed
string siteUrl = req.GetQueryNameValuePairs ()
.FirstOrDefault (q => string
.Compare (q.Key, "url", true) == 0)
.Value;
dynamic data = await
req.Content.ReadAsAsync<object> ();
siteUrl = siteUrl ?? data?.url;
if (siteUrl == null) {
return req.CreateResponse (HttpStatusCode.BadRequest,
new { body = "'url' query string parameter is missing" });
}
else {
// check for site quota of site
//todo - Implement site quota
CheckSiteQuota(req,siteUrl);
}
}

Get Site Quota

Use below code to get site quota:

public static System.Net.Http.HttpResponseMessage CheckSiteQuota(HttpRequestMessage req, string siteUrl)  
{
string baseUrl = "https://tenant.sharepoint.com";
string tenantUrl_CONFIG_KEY = "tenantUrl";
string managedPath = "/sites/";
string clientId_CONFIG_KEY = "clientId";
string clientSecret_CONFIG_KEY = "clientSecret";
string clientId = System.Environment.GetEnvironmentVariable(clientId_CONFIG_KEY, EnvironmentVariableTarget.Process);
string clientSecret = System.Environment.GetEnvironmentVariable(clientSecret_CONFIG_KEY, EnvironmentVariableTarget.Process);
string tenantUrl = System.Environment.GetEnvironmentVariable(tenantUrl_CONFIG_KEY, EnvironmentVariableTarget.Process);
if (string.IsNullOrEmpty(clientId) || string.IsNullOrEmpty(clientSecret) || string.IsNullOrEmpty(tenantUrl))
{
req.CreateResponse(HttpStatusCode.BadRequest,
new { body = "Application configuration missing for Function App" });
}
string completeUrl = baseUrl + managedPath + siteUrl;
OfficeDevPnP.Core.AuthenticationManager authManager = new OfficeDevPnP.Core.AuthenticationManager();
ClientContext tenantContext = authManager.GetAppOnlyAuthenticatedContext(tenantUrl, clientId, clientSecret);
Tenant tenant = new Tenant(tenantContext);
try
{
var properties = tenant.GetSitePropertiesByUrl(completeUrl, false);
tenant.Context.Load(properties);
tenant.Context.ExecuteQueryRetry();
return req.CreateResponse(HttpStatusCode.OK, new { quota = properties.StorageMaximumLevel.ToString(), warning = properties.StorageWarningLevel.ToString() });
}
catch (Exception ex)
{
return req.CreateResponse(HttpStatusCode.OK, new { Exception = "Server Exception. Unable to get site details " + ex.ToString() });
}
}

Testing Azure Function API

You can test API directly from within Azure Function. Expand Test section, Add below json to our Request body

{
"url": "dev"
}

When you run this function, you should see output as below json:

{
"quota": "26214400",
"warning": "25574400"
}

Getting Azure Function Endpoint

Click on get </> Get Function Url to get endpoint url to call this function. You can either select default Function key or master host key or default host key for authentication purpose.

This is your Azure Function API endpoint which should be called by passing ‘url’ as queryString parameter : https://sumitfunction.azurewebsites.net/api/AzureFunctionCSOMAPI?code=codeForYourFunction&url=siteUrl

The only remaining part is calling this Azure Function endpoint from SharePoint. Now you know how powerful and simple Azure Functions are!

--

--