Convert files to PDF using Microsoft Graph & Azure Functions
By: Philipp Bauknecht
Tags: Office 365, Microsoft Graph, Serverless, Pdf Converter, Azure Functions

Prerequisites

Microsoft Visual Studio 2019 with Azure Functions Tools

Download free as Community Edition here: https://visualstudio.microsoft.com/vs/community/

as Community Edition here: https://visualstudio.microsoft.com/vs/community/ Office 365 tenant

Microsoft provides free Office 365 developer tenants when you join the Office 365 developer program here: https://developer.microsoft.com/en-us/office/dev-program

when you join the Office 365 developer program here: https://developer.microsoft.com/en-us/office/dev-program Azure subscription to deploy the Functions app to

Sign up for a free Azure subscription here: https://azure.microsoft.com/en-us/free/

Step 1: Create a new Azure Functions app

Open Visual Studio and create new Azure Function project. Make sure Azure Functions v3 (.NET Core) is selected and pick the Empty template.

Azure Function template selection dialog

Step 2: Create an OAuth2 authentication service to request an access token to call the Microsoft Graph

Setup authentication with credential flow in Azure Active Directory

Before we can talk to the Microsoft Graph we need to authenticate and acquire an access token using OAuth 2 credential flow. In our case we have no signed in user present instead we want to authenticate as a service. Therefore we will use the credential flow providing a ClientId and ClientSecret of an app registration in AzureAD.

So let’s start by creating the app registration in Azure AD. Go to https://portal.azure.com and sign in with a admin user of your O365 tenant, go to Azure Active Directory and select App Registrations

Add a new app registration, pick a name e.g. PdfConversionService. Account types and Redirect URI are not relevant for this authentication mode, so you can just leave those as they are.

Next we need to save the values of Application (client) Id and Directory (tenant) Id for later use in our function’s settings from here:

Next we need to create a Client Secret as credential for our service to authenticate. Therefore select Certificates & Secrets in the left menu and click the New Client Secret button. Pick a description and Expiration:

Also save the Client Secret for later use in our function’s settings.

Finally we need to add permission to read and write in our SharePoint for the app registration. Select API permissions and click the Add a permission button. Choose Microsoft Graph and pick Application permission. Application permission means that we act in the name of an application instead on behalt of a user (delegated permission). Search for file and select Files.ReadWrite.All:

After adding the permission we also need to grant this permission to the app registration. The button here for might take a moment to become active. When active click it and enter your credentials in the popup window:

Now we have completed the app registration configuration.

Function app settings for authentication

To use the credentials we have just created along with some additional authentication configuration let’s create a model for authentication options:

And of course we need to provide these options in our local.settings.json for local debugging:

Authentication Service

The authentication service will use those settings to request an access token that we can pass along with the request to the Microsoft Graph later. This can be done by a simple http request:

Step 3: Create a File Service to upload, convert and delete files using the Microsoft Graph

Function app settings for the file service

For our file operations we need to provide 2 options to a file service:

the Graph Endpoint to use and

the SiteId to upload and convert to files to

So like with authentication let’s start by defining an options model:

Creating a site and finding the site id in SharePoint

Before we can upload anything to SharePoint we need to create a new SharePoint site and get it’s id. So let’s create a new SharePoint site e.g. PDFDemo in the portal (https://portal.office.com → SharePoint).

Getting the id of a SharePoint site is actually a bit tricky as I have yet to find a place in SharePoint where it’s actually shown. My trick of getting it is using the Microsoft Graph Explorer (https://developer.microsoft.com/en-us/graph/graph-explorer), log in with the O365 admin account and calling this url: https://graph.microsoft.com/v1.0/sites/YOUR_SHAREPOINT_URL/:/sites/NAME_OF_SITE/?$select=id where YOUR_SHAREPOINT_URL is something like medialessondev.sharepoint.com. This will return a response like this:

File service settings

So let’s add the full value of the id along with the Graph endpoint to our local.settings.json:

Implement file service

The file service will provide 3 methods:

Upload a file to SharePoint

Convert the file to pdf

Delete the original file in SharePoint

The file service will use the authentication service to acquire an access token a use it for all 3 requests to the Microsoft Graph. So let’s pass the authentication service and the options in through the constructor and write a helper method to create a HttpClient that uses the access token:

Let’s add a new method to upload a file to our SharePoint site:

Please note:

I’m using the library MediaTypeMap.core to get the correct file extension by the file’s content type

It’s important to also specify the file’s content type in the request header

We just need to return the id of the saved file in SharePoint in order to work with this file in the following methods

Next we need to implement a method to convert this file to pdf and retrieve it from SharePoint. This can be done in a single Graph request providing the path, fileId and target format:

Finally we also need a method to delete the original file in SharePoint once we have successfully converted it:

Step 4: Setup Dependency Injection

In order to use the 2 services we just created along with their options we need to create them somewhere. This is where dependency injection comes in handy. To use dependency injection in Azure Function app we need to add the package Microsoft.Azure.Functions.Extensions to our app using Nuget.

With this package we can now configure our services and options in a startup class:

Step 5: Create a new function

Add a new function to your project and name it ConvertToPdf. Select the Http trigger so our function can be called via a http request and pick Authorization level Anonymous so we don’t need to provide any credentials when calling this function.

Function configuration dialog

In order to use dependency injection in this function the class and method need to be NON static. Also we need to inject the file service and the pdf options into the constructor and save them into readonly fields:

Step 6: Upload the input file to a drive

With all services and settings and plumbing in place we can upload the file we receive in the function method using our file service:

Please note how the path variable is composed to point to the root folder of the SharePoint site.

Step 7: Download the file in pdf format

Next step is to download the pdf converted version of the file we just uploaded using the file id:

Step 8: Delete the original file from the drive and return the pdf

Almost there! Before returning the converted pdf file to the caller of the function let’s clean up by deleting the original file from SharePoint:

We made it!

Summary

This was a long post but I hope you still enjoyed it. I think this is a pretty convenient way of converting files to pdf in case you are in a scenario where you already have Office 365. The Azure AD authentication part is some work but can be reused in many ways when interaction with the Microsoft Graph. Doing this in Azure Functions lets me provide this functionality as a micro service to existing business processes and is free for up to 1 million requests per month.