Flow Examples: Note attachment to SharePoint
In a recent post, we looked at leveraging Dynamics 365 to build Line of Business (LOB) applications: Dynamics 365 Line of Business Applications, specifically focused on what we previously called Dynamics CRM and XRM development. The post highlights Dynamics 365 platform capabilities for building customized applications to suit specific business needs. With each major release, Microsoft debuts new features that help us deliver LOB solutions that require less development. One significant example of this is Microsoft Flow. This service has been around for a few years and it’s matured into a powerful tool for building configurable workflows that connect systems. I recently had a opportunity to test out Microsoft Flow for a customer demonstration that warranted a share.
Automation with Flow
Dynamics 365 can now be extended past just Entities, Plugins, and Workflows using services such as Microsoft Flow, PowerApps, and PowerBI. The Microsoft Flow website calls this the Microsoft “Power Platform” which is a pretty catchy name. Microsoft Flow is the Power Platform tool that allows user to:
Create automated workflows between your favorite apps and services to get notifications, synchronize files, collect data, and more
That is a catchy tagline but it does make a point: Flow is poised to become the new Workflow engine for Dynamics. I hear rumblings that soon Flow will be the only method available for configuration based CRM Workflows. I am not sure how true this is, but Flow looks like a pretty solid move by Microsoft. We can set up Flows that operate like CRM Workflows and act on your CRM data only. Or we can configure connectors and quickly integrate with external systems such as SharePoint, OneDrive, Dropbox, or Slack.
We are demonstrating a Dynamics 365 solution to a potential customer that includes Dynamics Portals as part of the package. One big limitation with the current version of Portals is moving uploaded documents into SharePoint. Portals integration with SharePoint had been a feature in the past and it is now scheduled to return with the fall release. Check out the October 2018 release notes section on the Portals SharePoint integration: Manage SharePoint documents. This looks like a solid feature that will remove a lot of custom code for many customers.
Unfortunately, this feature is not slated to be released until October and our demonstration is this week. This is not a new problem and can be handled via code. But one goal of our demonstration is to show “low code, no code” solutions using the Dynamics CRM platform. So I decided to see if I could build a configuration only solution: Create a Flow that will copy a new Note attachment uploaded through the Portal to SharePoint.
Short answer: it works! I was able to configure a Flow that triggered on with a new file uploaded from the Portal. Our portal demonstration leverages the Customer Self Service Portal website and we’ve configured file uploads to create a new Note directly on the Case rather than the Portal Comment record. So my sample Flow responds to a new Note created for a Case and will copy the file to the Document Location(s) associated to the Case. Here are some of the details on the Flow configuraton.
Trigger on Note creation
The trigger for the Flow is the creation of a new Note and the trigger has the following settings:
This step is fairly basic. Choose the Entity type of Note against which we want to trigger our Flow. This establishes context similar to what we see in a CRM Workflow or Plugin where the Target record is available for processing.
Capture the related Case
The next step is to capture the Case related to the Note. This makes the Flow very specific, only handling Notes with a Regarding set to the Case Entity. The Item Identifier field is populated from the initial trigger of Note creation. We now have the Case available as part of our Flow, again similar to CRM Workflows where we can work on records related to the Target. I think a better design would be to introduce a check condition following this step to ensure that the Case is not null. If it is null, we can stop the Flow.
Wait just one minute…
During my initial testing, I was creating a new Case from the Portal. This meant CRM creates the Case and then creates a new Note with the Attachment. I tested by creating the new Case but when the Flow triggered, default Document Location for the Case was not yet available, causing the failure. With existing Cases, this should not be an issue but for new Cases I needed to add a simple wait condition. Here is a chance to add some logic to the flow through an expression. For the wait condition, we add 1 minute to the current time and set that into a variable. The expression is a simple function call:
That new time value is then used by the Delay Until action, resulting in a simple wait condition for the Flow.
I chose a minute to wait, but under more load than a demo, a minute might not be enough time. I think a branch condition might work better in the real world for this situation. If the list of Document Locations is not empty, then move on to the upload step. If no Document Locations exist, then wait until they are available. This could be a chance to leverage a Do Until step: wait until the result set returns more than one record.
This is the kind of situation that would require some testing for a real world deployment. For example, could we create an unending Do Until loop if the Document Location creation fails?
List the Document Locations
Now that we have the Case and we gave it a minute to create the Document Locations, we need a Flow Action to retrieve the list of Document Locations for the Case retrieved in previous steps. The Document Location records will tell us where to upload the file. This is a fairly simple Action but it has some tricky bits if you are not a developer because it requires Web API syntax for its filter criteria. Luckily, the CRM Rest Builder tool by Jason Lattimer is a big help in building the Filter Query.
You can see the Case reference used in the Filter Query parameter and I’ve included a Top Count value of 1 to limit the results to one record. For my demo, I should only have the one default Document Location created, so this value is essentially optional for my current scenario. But these additional filter options could be important in live deployments. If my deployment included multiple document locations, this file would be uploaded to each folder. This can be handled with some additional criteria in the Filter Query like the Location Name.
Upload the new file
This step does the hard work of actually taking the Note attachment and crating the file in SharePoint. It’s actually pretty simple if you look at the Action definition. This is an Apply to each step which means Flow will allow you to apply a series of Actions to each value returned in the previous step. Within the Apply to each loop, we include a SharePoint Create File Action to create the file.
In this Action, you specify the SharePoint root URL in the Site Address, the Folder Path for the file, the File Name, and then the File Content. The Site Address will auto populate from your SharePoint connection and the Folder Path is built using the Relative URL via the current Document Location. Including ‘incident’ in the Folder Path is another example of the Flow being specific to a Case but I think with a bit of work, we could make this step a bit more flexible. But for the purposes of my demo, I decided to leave it in place.
The File Name is straightforward since it’s an attribute on the Note from the triggering step. But we have the Note attachment contents returned as an encoded string in the Note Document attribute. Outside of just learning the basics of Flow, this was the tricky part. Luckily, the Flow expressions allowed me to convert the Document body into a binary stream with just one line:
During my initial testing, the new file was being created, but the contents were the base64 string. That just doesn’t work for a Word Document or PDF! This expression takes the base 64 encoded string and converts into the format required for the SharePoint action. Using this one line solution, we can preserve the file contents when creating the new file.
The test below was a 10 MB PDF that I attached as a note and it was successfully moved to my Case Document Location.
This is a great demonstration of the Microsoft Power Platform capabilities: quickly building solutions that would otherwise require custom code via Dynamics CRM plugin or workflow and some additional code to handle the calls to the SharePoint APIs. In about an hour or two, I was able to configure file upload to SharePoint from a Note attached to a Case. This is one of the first Microsoft Flows that I attempted and I got this to work with only a bit of digging into the documentation.
I really did not dig into another aspect of Microsoft Flow and the rest of the Power Platform services: infrastructure and tooling. I build the Flow in a pretty user friendly designer and I was able to test my logic with a few clicks. The logging and tracing provided by the Flow tools is powerful as it provided Action inputs and results with very informative error messages. As a developer, this kind of tool is an incredible time saver and very hard to build! I’ll definitely be writing a post or two about the designer tools in the future.
As always, comments, questions, corrections are all welcome. I am also interested in hearing more about your experiences with the Microsoft Power Platform services.
2 thoughts on “Flow Examples: Note attachment to SharePoint”
This is a great use of flow – I’ve used this with previous clients to move attachments to notes over to SharePoint. One issue though – you are triggering on the creation of a note, and you really should limit the flow to only trigger on the creation of a note WITH AN ATTACHMENT. Otherwise, you’ll get FLOWS triggering when there is no attachment to move. To do so, add “isdocument eq true” in the settings of the “New Note Created” step.
I totally agree. The additional flag will add a level of filtering and avoid some error checking for the body downstream. This example is actually using the deprecated Dynamics 365 connector and those filter options were not available as they are in the new ‘Common Data Service (current environment)’ connector. Basically, I need to update my example!
Thanks for taking the time to comment and share your experiences!