As I’ve described recently, I’m working on a Provider-Hosted SharePoint App that’s hosted in Azure. I’ve said previously about using Remote Event Receivers, and this whole app is really about sending emails from SharePoint Online (which we’re doing via SendGrid).
One of the things the customer wants is ‘timed’ emails – that is, some sort of service that talks to SharePoint Online, checks to see if there are any items in a list that are due for action, and if so sends an alert email. Simple enough, but with one minor problem. There are no timer jobs in SharePoint Apps. And you can’t put them into Office 365. And Azure doesn’t have an equivalent … yet.
Microsoft have announced that there’s going to be an Azure Scheduler service. This is currently in preview, though it looks pretty complete to me:
This service will, according to a schedule you define, either make an HTTP(S) request, or can add an entry to a Storage queue. I decided to use an HTTP request, and I wrote code to handle that request in my Azure Website. (Okay, I created a page, and put the work I needed to do into the code-behind’s OnLoad event).
Now, this does have some disadvantages still over a proper timer job. For example, the thread will still timeout after about 60s – which isn’t very long. However, for my scenario of sending alert emails it was long enough – I could grab a batch that needed alerts sent, and any that weren’t processed yet might get picked up on the next run. In short, rather than running once and trying to do lots, I set up my ‘job’ so it runs frequently, but only processes a few items each time.
The second issue that I faced was actually authenticating with SharePoint Online. This interaction is a bit different to most that happen in an app – it wasn’t user initiated, and there wasn’t a user token to authenticate with SharePoint with. I could store an account name and password in my Azure website’s config, but how would I use that?
Well, the obvious candidate was SharePointOnlineCredentials class. This worked fine in debug, but unfortunately when I tried to use this when published to Azure I got the exception:
[System.IO.FileNotFoundException] – msoidcliL.dll (Microsoft.SharePoint.Client.Runtime)
at Microsoft.SharePoint.Client.Idcrl.IdcrlNativeMethodsSelector..ctor(String dllPath) at Microsoft.SharePoint.Client.Idcrl.ManagedIdcrl.get_IdcrlNativeMethods() at Microsoft.SharePoint.Client.Idcrl.ManagedIdcrl.EnsureInited() at Microsoft.SharePoint.Client.Idcrl.ManagedIdcrl.LogonIdentity(String username, SecureString password) at Microsoft.SharePoint.Client.Idcrl.SharePointOnlineAuthenticationProvider.Logon(String username, SecureString password) at Microsoft.SharePoint.Client.SharePointOnlineCredentials..ctor(String username, SecureString password) at DS.Goodman.EmailAlertsWeb.Pages.SendAlertEmails.Page_Load(Object sender, EventArgs e)
Azure doesn’t have the SharePoint Server 2013 Client Components SDK installed on it, and that appears to be a problem. So, what could I do? Was there any way around this?
Fortunately I found a blog post by Chris Johnson about “‘Headless’ Authentication with SharePoint Online and the Client Side Object Model” In it he details how to authenticate with SharePoint Online without using the tools in the Client Components SDK (actually, I suspect this approach pre-dates those components). I copied his approach from the example application he provided and (once I added the trailing / to my site collection URL) it worked.
So, now my Azure Scheduler service can make a request of my Azure website, and it can then authenticate and query SharePoint Online, and finally kick out an email via SendGrid. Which is neat, and gives the world more email…