cancel
Showing results for 
Search instead for 
Did you mean: 

Microsoft Flow as a Service

In this blog, I will show how to create a flow that can be used as a service. We will create a customer request management service using Flow, SharePoint and a Web app. A user can create a new request through the page by entering the details and upload an attachment. A unique code is generated once the request is processed and the customer can track their request by entering this code and their email address.

The idea here is, a user is navigated to the contacts page to file/ get status of a request. The page has two tabs:

First: where they can create a new request by entering the name, email address, comments and attach an image file. There is a submit button that takes all these inputs and then sends a POST request to the Flow with all the inputs as a JSON body. These inputs are then parsed in Flow and an item is created in SharePoint. An acknowledgement email is sent to the user and an email with these details is sent to the concerned customer support department in the company. A unique code is generated and sent as a response that the user can view on the Contact page.

Second: takes the unique code and the email address of the user as inputs to get the request status from SharePoint through the Flow. These inputs are parsed in Flow and the relevant item is extracted from SharePoint and if the details match, the status is sent as a response to the web app and displayed to the user. If there is a mismatch, an error notification to enter correct details is displayed to the user.

Let’s get started.

Web App:

The web application is a simple app hosted in Azure. I created a basic ASP.NET application using Visual Studio and made some modifications to the Contacts.cshtml page.

I added a few input tags, buttons and added some javascript code to invoke the flows when the buttons are pressed.APiB1.PNG

Tab1: 

<div>You have reached the request page. If you have already placed a request, try the request tracker. If not create one here.</div>
<br />
<fieldset>
    <legend>Create a new request</legend>
    <br />
    Name :
    <input id="nameEntry" type="text" value="" style="Width:20%" />
    <br />
    Email :
    <input id="email" type="text" value="" style="Width:20%" />
    <br />
    Comments :
    <input id="comments" type="text" value="" style="Width:20%" />
    <br />
    Upload Image :
    <input id="file" type="file" name="pic" accept="image/*">
    <br />
    <button id="sub" name="temp" value="temp" onclick="userAction()">Submit Request</button>
    <br />
    <br />
    <span id="newReq"></span>
</fieldset>

Script to add an image file as an input to the first flow: Source

var tempFile
    if (window.File && window.FileReader && window.FileList && window.Blob) {
        document.getElementById('file').addEventListener('change', handleFileSelect, false);
    }
    function handleFileSelect(evt) {
        var f = evt.target.files[0]; // FileList object
        var reader = new FileReader();
        // Closure to capture the file information.
        reader.onload = (function (theFile) {
            return function (e) {
                var binaryData = e.target.result;
                //Converting Binary Data to base 64
               tempFile = window.btoa(binaryData);
                //showing file converted to base64
            };
        })(f);
        // Read in the image file as a data URL.
        reader.readAsBinaryString(f);
    }

Script to invoke the first flow:

const userAction = async () => {
        var data = { name: document.getElementById('nameEntry').value, email: document.getElementById('email').value, comments: document.getElementById('comments').value, file: tempFile };
            const response = await fetch('https://prod-03.westus.logic.azure.com:443/workflows/keyinfo/triggers/manual/paths/invoke?api-version=2016-06-01&sp=%2Ftriggers%2Fmanual%2Frun&sv=1.0&sig=keyinfo', {
                method: 'POST',
                body: JSON.stringify(data),
                headers: {
                    'Content-Type': 'application/json'
                }
            });
            const myJson = await response.text();
            document.getElementById("newReq").innerHTML = myJson;
        }

Tab 2:

<fieldset>
    <legend>Track a request</legend>
    <br />
    Email :
    <input id="emailReq" type="text" value="" style="Width:20%" />
    <br />
    Request Id :
    <input id="requestCode" type="text" value="" style="Width:20%" />
    <br />
    <button id="getreq" name="getRegq" value="GetReq" onclick="getreqs()">Get Status</button>
    <br />
    <span id="oldReq"></span>
</fieldset>

Scrip to invoke second flow:

const getreqs = async () => {
        var data = { emailID: document.getElementById('emailReq').value, reqNo: document.getElementById('requestCode').value };
            const response = await fetch('https://prod-11.westus.logic.azure.com:443/workflows/keyinfo/triggers/manual/paths/invoke?api-version=2016-06-01&sp=%2Ftriggers%2Fmanual%2Frun&sv=1.0&sig=keyinfo', {
                method: 'POST',
                body: JSON.stringify(data),
                headers: {
                    'Content-Type': 'application/json'
            }
                });
            const myJson = await response.text();
            document.getElementById("oldReq").innerHTML = myJson;
        }

Flow:

There are two flows that we will be using here:

1. For new Requests:APiB2.PNG

Step-1: Trigger- When an HTTP request is received: Schema:

{
    "type": "object",
    "properties": {
        "name": {
            "type": "string"
        },
        "email": {
            "type": "string"
        },
        "comments": {
            "type": "string"
        },
        "file": {
            "type": "string"
        }
    }
}

To get the details from the requestor.

Step-2: Create item in the SharePoint List based on inputs received from the user. 

Step-3: Create the attachment received on the item created in the previous step.APiB3.PNG

Step-4: Send an email: send an email notification to the concerned department regarding the request that was created.

Step-5: Send an email: send an email notification to the user acknowledging the receipt of the request.

Step-6: Send a response: Send response to the app with the details of the request ID and successful filing of the request.

2. For existing Requests:APiB4.PNG

Step-1: Trigger: When an HTTP request is received: Schema:

{
    "type": "object",
    "properties": {
        "emailID": {
            "type": "string"
        },
        "reqNo": {
            "type": "string"
        }
    }
}

Step-2: Initialize a string variable: This gets the ID in string format from the request received. Expression:

last(split(tolower(triggerBody()?['reqNo']),'req'))

Step-3: Get Item from SharePoint: To get the request details from SharePoint. Expression:

int(variables('id'))

 

APiB5.PNG

Step-4: Condition Control: To check if the user has input the correct email address. 

//Yes Branch

Send response along with the request details.

//No Branch

Send error notification.

//End condition

In this blog, we saw how to create simple low code no code end to end processes using Flow and invoke them as an API with custom inputs. As long as the action control can trigger an API request this configuration can be used across web apps and such services (including bots etc.) with minimal coding involved.

I hope you found this interesting and it helped you. Thank you for reading!

Comments

Hi @yashag2255 ,

 

Thanks for sharing this helpful blog.

I have tried to implement the same tutorial but there is a problem that occurs on the attachments because it's not sending the file content with type base 64 in the request. So after checking for the attachments in the items,the images are not displaying.

Any solution for this issue ?

Thanks again!

Hi @Julien2 

 

Can you share a screenshot of what you are getting for the file part? Based on that we should be able to convert to binary or base 64 and create the attachment file. 

 

Hope this Helps!

Hi @yashag2255 ,

Here is a demo on how i am filling the form,uploading the image and showing the results after those actions:

Demo.gif

Here is the flow result of the file content:

Capture.PNG

I am using .NET Core 3.0,I've changed the design only on index.cshtml,and i don't think this will affect to upload images anyway here is the html code:

<h5><span class="badge badge-dark">Upload Image</span></h5>
    <div class="custom-file p-4">
        <input id="file" type="file" name="pic" class="custom-file-input" style="margin-top:25px;" accept="image/*">
        <label class="custom-file-label" for="file" style="margin-right:850px;">Choose file</label>
    </div>
    <br />
    <button id="sub" name="temp" value="temp" onclick="userAction()" class="btn btn-dark">Submit Request</button>
    <br />
    <br />
    <span id="newReq"></span>

JS code:

  <script>
var tempFile
    if (window.File && window.FileReader && window.FileList && window.Blob) {
        document.getElementById('file').addEventListener('change', handleFileSelect, false);
    }
    function handleFileSelect(evt) {
        var f = evt.target.files[0]; // FileList object
        var reader = new FileReader();
        // Closure to capture the file information.
        reader.onload = (function (theFile) {
            return function (e) {
                var binaryData = e.target.result;
                //Converting Binary Data to base 64
               tempFile = window.btoa(binaryData);
                //showing file converted to base64
            };
        })(f);
        // Read in the image file as a data URL.
        reader.readAsBinaryString(f);
    }
        const userAction = async () => {
            var data = { name: document.getElementById('nameEntry').value, email: document.getElementById('email').value, comments: document.getElementById('comments').value, file: tempFile };
            const response = await fetch('URL', {
                method: 'POST',
                body: JSON.stringify(data),
                headers: {
                    'Content-Type': 'application/json'
                }
            });
            const myJson = await response.text();
            document.getElementById("newReq").innerHTML = myJson;
        }
    </script>

It shows that the file is converted to base 64 but why it's not displaying the image in the attachment ?

Looking to hear from you.

 

Thank you!

Hey @Julien2 

 

So after a deeper dive into this, here is what I found: 

1. If you are uploading an image of extension PNG, then it will directly give you the appropriate base64 that you can directly upload and get the image. 

 

2. If you are uploading a JPEG/ JPG type images then there is that issue that you are seeing. So here is how you can resolve it: 

 

ee22.PNG

 

And if this resolves the issue, please mark the thread that you have created as solved as it might help other folks who face similar issues resolve soon. 

 

Note: Use this compose action for PNG type images too. It works for both.

 

Hope this Helps! 

Hi @yashag2255 

 

Hi

Thank you very much for your support, now it works like charm.I'll post this solution in the thread that i have created.
I just want to understand about "Using this compose action for PNG type", because I've uploaded an image of PNG type using the compose you mentioned and the image display like the others, while the File-Name in the "Add attachments action" is "Title".jpg:
cap1.PNG

Thanks again!

Hi @Julien2 

 

The file format shouldn't matter much while creating as we are providing the MIME type of image/JPEG that includes PNG, JPG and JPEG. 

 

Hope this Helps!

Meet Our Blog Authors
  • Working daily with Microsoft Cloud to deliver the needs of my company, my customers and various Microsoft communities and forums. | Office 365 | Flow | PowerShell | PowerApps | SharePoint |
  • Co-founder of https://plumsail.com, Office 365 and SharePoint expert. Passionate about design and development of easy to use, convenient and flexible products.
  • Microsoft Business Apps MVP. Owner of ThriveFast, an Office 365 consulting company.
  • 7x Microsoft Business Solutions MVP (CRM)
  • I'm keen in MS technologies, SharePoint, Office 365 and development for them
  • Daniel is a Business Productivity Consultant & Microsoft Business Solutions MVP who is very enthusiastic about all things Office 365, Microsoft Flow, PowerApps, Azure & SharePoint (Online). Since the preview, Daniel has been working with Microsoft Flow and later on with Microsoft PowerApps. That led to him being awarded an MVP Award for Business Solutions. He loves to blog, present and evangelize about improving productivity in the modern workspace with these amazing tools!
  • Michelle is an Office 365 solution architect in Twin Cities, MN. She has been delivering business collaboration solutions for years with her focus on SharePoint and Office 365. Michelle is a recent board member of the Minnesota Office 365 User Group and has been a member of the SharePoint community since 2009. She is a frequent speaker at MNSPUG and SharePoint Saturday and co-chaired the Legal SharePoint User Group for 4 years. Her most frequent projects have involved rolling out a large deployment of Office 365, SharePoint Online intranet, build of a "CHAMPS" Office 365 user adoption program and most recently, SharePoint On-Premise to Online Migration. Michelle is very excited about cloud technology as it is shifting her IT Pro focus to collaboration strategy and technical adoption.
  • I'm a Microsoft Office Servers and Services MVP with a special interest in SharePoint, Office 365, Microsoft Flow, Microsoft Teams and PowerApps. I work at Triad Group Plc ( https://triad.co.uk)
  • Passionate #Programmer #SharePoint #SPFx #Office365 #MSFlow | C-sharpCorner MVP | SharePoint StackOverflow, Github, PnP contributor