From Office 365 to Azure Event Grid, the events must Flow

Photo by Archana More on Unsplash

In this blog post, we capture all the events across an Office 365 Tenant from multiple event sources, gather them, and send them through an Azure Event Grid.

We then listen, filter and handle our events in a central, unified way.

The events must Flow.


This is also the full write up of this microblog posted to Twitter #FlowNinja earlier this month.


Plan

  1. What benefit do we get from this?

  2. Listen to every event across an Office 365 Tenant

  3. Construct a uniform event message

  4. Send them into a Serverless Event Solution - Azure Event Grid

  5. Filter and catch our events

We want to build 3 Flows

flow-event-grid-1.jpg

What benefit do we get from this?

First, we see the increasing availability of event hooks - we have subscriptions, delta queries, or webhooks, across various different products in Office 365. Some products like SharePoint is getting a SocketIO webhook. There will be more events, and our event handling design must evolve.

Second, we see the cost-effective solutions to handle these ever increasing flood of events in the form of Serverless compute. This is true with Azure Functions, Microsoft Flow or Azure Logic Apps.

We end up with a lot of individual event sources and a lot of individual event receivers. This is a common event handling problem. As number of events we handle increases, the worse the event management problem becomes.

Consider you have a “handle a document uploaded to a library” event - a very typical SharePoint Workflow. Now consider this library is cloned to a hundred project sites.

If we clone the event handler a hundred times, we have a problem.


If you have already done this with Flow, then try https://FlowStudio.app to help you manage them.
Ooh inline product placement!


If you are a developer, then consider this scenario.
Consider a typical event handling in the browser. A decade ago we used jQuery like this:

// 2008
$('button').click(handler);

// 2018
$(global).on('click', 'button', handler);

And gradually we find that unacceptable, because we have buttons, events everywhere, and managing individual event hooks was tedious and error prone. Eventually, we moved to a global handler model, and we filter just prior to event being raised.

The headache-less way to handle events is to set the hooks all at the global root level, and then filter by the event source and event type.

That is the exact reason we need Azure Event Grid.

  • Centrally manage our events

  • Decouple the event source from event handlers

  • Stay sane, with a hard problem

Listen to every event across an Office 365 Tenant

I had previously wrote about listening to Office 365 Management API via the HTTP action and app-only permissions. What I did not realize was that the Office 365 Management API also have fantastic webhooks.

I read about the webhooks from Kent Weare’s post, where he uses this event to get a trigger when Flows are created in the tenant.

https://flow.microsoft.com/en-us/blog/automate-flow-governance/

These are grouped into several categories: AzureAD, Exchange, SharePoint and General (other).

This is the subscriber. One picture of 4 blocks. I’m subscribing to three webhooks at once.



The Office 365 Management API is a fantastic general event source. The downside is that it’s not instant - event handler is called between 10-20minutes after the actual event. So it is great as an audit webhook, or for scheduling files or search or to signal for a bot to re-scan a document. But it’s not an instant webhook.

Of course, if our goal is to send events into an Event Grid - we can work with multiple event sources at the same time. We can add Microsoft Graph events or subscribe to SharePoint list webhooks directly.

This is the top of the Listener

Construct a uniform event message

The event grid has a event JSON structure, it also supports a CloudEvent structure.

When I built my implementation, the Event Grid connector is still in preview and I had troubles publishing a Cloud Event structure. I assume this wouldn’t be a problem anymore as the connector evolves.

This is the final loop design - all done.

Remember, we are running Serverless so abuse/utilize every opportunity to use as many Azure Servers as you can - if you can fan-out to parallelism you must.

Don’t talk to each individual HTTP action one at a time. Do (up to 50) all at the same time.


Send them into a Serverless Event solution - Azure Event Grid

The Azure Event Grid is a serverless event processing pipeline. It decouples our event source(s) from our event handlers.

Here is our first handler.

This catches every event on the Event Grid - in Event Grid, we see we have our first webhook attached - it appears as a LogicApps webhook.

Here are three examples of what it caught:

  • Flow created Event

  • Site Collection created Event

  • File uploaded Event

flow-event-grid-3.jpg

Filter and catch our events

We see the very specific webhook now registered on the event grid - and the filters are also listed

PPTX filter only runs when the file I’ve uploaded is a PowerPoint file.


Summary

I have been talking a lot about Serverless and how our tools and design must evolve. Having a unique Office 365 to Event Grid solution is something I talked about as far back as 2017. I’m glad a year later I’ve finally got a great prototype going.

  • Office 365 Management API is a great webhook source that catches all sorts of events. The downside is that it is an audit webhook, so the delay may not be acceptable to your needs.

  • Using Azure Event Grid to perform filtering and subscription gives us the unique ability to see EVERYTHING that’s going on in our tenant. That has tremendous value.

  • Because event source and event handling is now decoupled - we can add new event sources to push to the same Azure Event Grid. We can do this from Microsoft Graph, we can do this from SharePoint, or we can do this from a whole myriad of triggers available in Microsoft Flow

  • We can write Azure Functions to trigger off the Event Grid, and it would be visible as well.

  • I was reading and appreciating sending events to the new Azure SignalR service from Azure Functions - that would be pretty amazing to convert an event grid message into a websocket event.
    https://twitter.com/nthonyChu/status/1044427579460145152

The possibilities are endless. Our tools and our design must evolve.

Office 365 Saturday Adelaide - 2018 September 15

sps-adelaide.png

So it is said - there's always a SharePoint or Office 365 Saturday every Saturday around the world.

 


O365 Saturday Adelaide / SPS Saturday Adelaide

In less than two weeks, we'll converge in Adelaide Australia for September 15 2018 SharePoint and Office 365 Saturday.

This is a free event (held at Microsoft Adelaide this year) for Office 365 and SharePoint experts, developers, admin and powerusers to converge and talk about Office 365.

https://www.meetup.com/O365-Saturday/events/254139366/

This year I'm presenting an ever evolving talk around Microsoft Flow and what it can (and SharePoint's old Workflow platform can't do).

Hope to see you in Adelaide!

A small favour - share this with two people

Every year we reach out and people that come to the event tells us it's a great event but they wish they know about it earlier.  So here's our small ask:

If you are in Adelaide, please come, and please tell two other colleagues about this.
If you aren't in Adelaide - but you have colleagues in Adelaide, please tell them about this event.

 

 

 

The simplest No-Code Solution to Save Picture Files from PowerApps to Flow

pexels-photo-1028624.jpg

Today, we are going to talk about a new technique (hack) to send any pictures from PowerApps to Flow.

We will do this with a modified Flow Button trigger.


Update 2019-04 Save Picture Files from PowerApps to Flow via unused Outlook Connector

I’ve came up with an EVEN EASIER hack that you should check out. The 2019 April method is the best one so far.

http://johnliu.net/blog/2019/4/flowninja-hack-87-lock-microsoft-flow-powerapps-trigger-to-upload-images-to-sharepoint-with-ease

Update 2019-03 there’s some JSON definition changes to the PowerApps trigger. See note below.

Update 2019-01 - I did a YouTube recording of this blog post

Quite possibly the easiest way to let us upload an image from PowerApps into SharePoint - from the Add Pictures control (not the low res camera control). Without having to write a custom connection. By hacking a Flow Button into a PowerApps trigger.

Why John, what is the problem? 

Why do you repeatedly write the same post?

The problem is that we want to use PowerApps to collect binary files (mainly images, but also documents, video, anything) and send them to Flow - Flow can then decide where to send the pictures.  To SharePoint, to Email, to Cognitive Services etc.

This is a problem that isn't out of box, and has several good workarounds - some choices more difficult (or limited) than others.

 

What have we got so far?

This is the first method - we can send PowerApps' Camera to Flow via a built in dataUriToBinary() expression.  But it doesn't work for Add Picture from device gallery.  We also can't use this method for sending files - documents, zip, sound, movie clips.

This method lets us use Add Picture from gallery and we can send any binary file formats.  But the input parameter is specialized multipart formdata bytes, so this method needs a Custom Connection (need a Swagger definition file) to work with PowerApps.

 

What is this new method?

We are going to take a Flow Button and hack it into a PowerApps trigger to send Files from PowerApps to Flow.

It will be magical.  Because there will be no Swagger.

 

1. Build a Button-triggered Flow

We start with a Flow Button trigger - which lets us specify which parameters we want as part of the button click.  Flow Button let us select File.

Create FileName and FileContent compose actions to extract the value from the File trigger parameter.  Then use SharePoint's create file to create this file.

Test this Flow - upload a picture of LEGO 10234 - success.

 

2. Examine this Flow Button trigger and switch it to a PowerApps trigger.

Next, we need to check the Flow button trigger and convert it to a PowerApps trigger.

This can be done via Exporting the Flow, open up the export in ZIP file, and change the JSON definition of the trigger.manual.kind from "Button" to "PowerApp".  But here I'm using a simpler way by opening the Flow using Flow Studio's Edit Flow JSON capability.

Try it: https://flow-studio.azurewebsites.net/welcome

Save the changed definition and this is now a PowerApp trigger.

Note: Have a look at the JSON schema generated for the Flow Button's file trigger parameter.  We'll need to know this later.

 

3. Build our PowerApp

Note - this is the Add Picture control.  Not the camera control.

Because our Flow is now a PowerApps trigger - it appears in the available list without us having to build a Swagger file.

The parameters needed is { file: { name: "x", contentBytes: ... }} 
This matches what Flow Button wants for a file upload.

 

4. That's it.  Done.

Run the PowerApps to test.

And the result - LEGO 851400 cup is uploaded to SharePoint via Binary.  No Swagger.

 

Future thoughts

Eventually, I hope we have a way to officially define the input parameters we want to use in a PowerApps trigger.  The way it currently works is awkward.  It should just use the same way that the Flow Button trigger works.

Until that day - this method is possibly the simplest way to send any binary files from PowerApps to Flow.  Because this method doesn't need custom connections - you might find this useful in not hitting your Flow plan limit of 1 custom connection.

Underneath the hood though, a Flow Button trigger is the same as a PowerApps trigger (they are both HTTP Request Triggers).

 

Download File:

https://github.com/johnnliu/flow/blob/master/FlowNinja-SendFileToFlow_20180728000358.zip

 

Bonus Exercises:

  • Create multiple files first in Flow Button before converting to PowerApps trigger.

  • In the definition, made some (but not all) of the file parameters required

 

Update: adding additional arguments

The converted PowerApps trigger works, but you may find it troublesome to edit the Flow after it was changed.  And attempts to use Ask Parameter in PowerApp Trigger within the Flow Designer will cause the PowerApp trigger to be regenerated, potentially breaking the file argument.

Instead, do this.  First make sure it is a Button trigger again.  

Then, create multiple arguments with the Flow Button

Note the two new arguments have very boring names text and text_1

Note the two new string arguments in addition to the file JSON record object.
Result:

 

2019-03 update

  1. When editing the Button trigger to Powerapp do:

    Change Button to Powerapp
    Rename variables to nicer ones file1 and file2 - rather than file and file_1
    fix up references within the Flow to point to triggerBody()?[‘file1’]?[‘name’] and triggerBody()?[‘file1’]?]’contentBytes’]

  2. In PowerApps - call Flow method with two files

  3. See result

Flow For-Selected-Item trigger and SharePoint Site Pages, in a detective story

This is a long blog post, there are two parts:

  1. How do you make a SharePoint For Selected Item in Flow, and have it appear on the SharePoint Site Pages library
  2. Explain the magic rituals you just did to figure all this out

The Problem

Paul Matthews reached out and asked if it's possible to create a "For a selected item" Flow against Site Pages.  

I was able to reproduce what he's asking fairly quickly.

 

The Solution

May be you just want the solution.  The solution is that you need to use the "list guid" as the custom value for the SharePoint For Selected Item trigger, not the List Title.

 

The Detective Novella

Ah you are still here.  OK, buckle yourself in, we are going another Flow adventure.

First, when realizing that the For a Selected Item doesn't appear in Site Pages, I immediately call the SharePoint REST method SyncFlowInstances()

I do this of course, with another Flow.

This returns empty array for SynchronizationData.  This means:

SharePoint Site Pages don't know anything about my Flow.  It thinks there's no Flow connected to it.

Create an Out of Box Request sign-off Flow on Site Pages

SyncFlowInstances returns this Request sign-off Flow

So we know Flow can run on the Site Pages library, just not "Our" Flow.

I want to compare the JSON definition differences.

The Request sign-off Flow is owned by the SharePoint list, not by me.  So I can't read its definitions (I can't even see it in my list of Flows view)

So I created a Flow to assign the Request sign-off Flow to me.

This is necessary to add myself as a Owner to this Flow.

Now I open these two Flows with Flow Studio.

I can see both the working Flow (on the left) and the not-working Flow (on the right)

https://flow-studio.azurewebsites.net/

Checking the trigger JSON, I find that the Flow on the right (not working) has "Site Pages" as the name, but on the left (working) has a GUID as its name.

Summary

We explained the problem - it is the Site Pages not appearing as a choice - it's not a List nor a base Document Library.  Typing the name "Site Pages" doesn't work.

The solution is to use the list Guid.

And the debugging steps takes us to SyncFlowInstances, Modify FLow as Admin to assign a new template flow back to me as the owner, and finally using Flow Studio to change the existing "Site Pages" to the list guid.

 

 

 

Office 365 Saturday Canberra 2018 #O365CBR #SPSCBR

This Saturday - 14 July, we'll be converging on SharePoint and Office 365 Saturday Canberra.  I'm planning to take my time and drive down for the weekend.

028Canberra0021.jpg

https://www.meetup.com/en-AU/O365-Saturday/events/252110689/ 

The event is held at Microsoft office this time (so not at the previous Clifton's venue).  We will be covering a mix of Office 365, modern SharePoint, and security topics.

I'll be around all day as well - ask me anything about SharePoint, Flow, PowerApps, Office Development, Todo, Xbox and everything!

I believe we have an Xbox One and a bunch of swag to give away too!  But you are definitely coming for the wide range of content and topics, and definitely not for the swag.

We hope to see you there!