Apr
23
Written by:
Michael Washington
4/23/2019 8:13 PM
You can create a Microsoft Flow that will allow you to send an Email to an Office 365 Email account and that will trigger a search for Help Desk Tickets in the popular open source Help Desk application ADefHelpDesk.com, and return an email to you with a listing of matching Help Desk Tickets.
The overall application flow looks like this:
- The user sends an Email to Microsoft Office account with the search term in the Subject field of the Email
- Microsoft Flow is triggered and invokes the Custom Connector to search the tickets in the ADefHelpDesk site
- The Microsoft Flow formats the response into an HTML table and sends an Email response to the user
The User Experience
The end user of the application sends an email to the Office 365 Email account, with the search term in the Subject field of the Email.
The Microsoft Flow kicks off, triggered by the Email.
This kicks off the Microsoft Flow step that invokes the Custom Connector to search the Help Desk Tickets in the ADefHelpDesk site.
The Microsoft Flow then formats that response into an HTML table and sends an Email back to the user.
Setting Up the ADefHelpDesk API
You can download and install ADefHelpDesk from the site at: http://ADefHelpDesk.com.
After you have the site running, follow the directions at the link: API Security (Swagger Rest API) on the documentation page (that can be found at this link), to create an account that can call the API.
You will need to copy the information on the Connection Information tab, for the API account, to use later.
In the ADefHelpDesk site there is a Swagger page (to learn about Swagger, see: https://swagger.io/), that documents the REST based API endpoints at: http://{your default web address}/swagger/ (for example: http://adefhelpdesk.azurewebsites.net/swagger/).
You will also want to create a few Help Desk Tickets, of various Statuses and Assignments, so that you have something to search for.
The Proxy Project
We create a proxy application that will sit between the Microsoft Flow and the ADefHelpDesk application for the following reasons:
- The ADefHelpDesk application will return a complex response that the Microsoft Flow will be unable to understand and consume. For example, ADefHelpDesk will return nested collections of tags related to Tickets. The proxy project will return a response that Microsoft Flow can understand.
- Before we can retrieve the Tickets in the ADefHelpDesk application, we need to obtain an authorization token (also called a JSON Web Token (JWT) or Bearer Token). Subsequent calls to the ADefHelpDesk API are made using this token. The proxy project will handle this requirement.
The full code is available on the download page of this site, but the relevant code is contained in the ADefHelpDeskController.cs file
The Microsoft Flow Custom Connector will communicate with the Proxy code by calling the SearchTickets method:
// GET api/SearchTickets
[HttpGet("SearchTickets")]
public async Task<ActionResult<List<DTOTask>>> GetAsync(
string APIWebAddress,
string userName,
string password,
string applicationGUID,
string searchText)
{
// Call the GetAuthToken method and retrieve the BearerToken (JWT - Auth Token)
DTOApiToken paramDTOApiToken = new DTOApiToken();
paramDTOApiToken.userName = userName;
paramDTOApiToken.password = password;
paramDTOApiToken.applicationGUID = applicationGUID;
// Call the ADefHelpDesk API to get a Authorization token
// using the username and password of the API account
string BearerToken = await GetAuthTokenAsync(APIWebAddress, paramDTOApiToken);
// *******
// Use the BearerToken to search the Tickets
// Note: pass a empty string to not search on a text parameter
// however, all integers must be set to a valid value
// except selectedTreeNodes can be null
DTOSearchParameters objDTOSearchParameters = new DTOSearchParameters();
objDTOSearchParameters.pageNumber = 1;
objDTOSearchParameters.rowsPerPage = 10;
objDTOSearchParameters.sortField = "createdDate";
objDTOSearchParameters.sortOrder = "desc";
objDTOSearchParameters.createdDate = "";
objDTOSearchParameters.dueDate = "";
objDTOSearchParameters.searchText = searchText;
objDTOSearchParameters.selectedTreeNodes = new List<int>();
// Call
var result = await SearchTasksAsync(
APIWebAddress,
BearerToken,
objDTOSearchParameters);
return result.taskList;
}
Before this method can retrieve the Tickets, it needs to obtain an authorization token (also called a JSON Web Token (JWT) or Bearer Token), using the following method:
private static async Task<string> GetAuthTokenAsync(
string APIWebAddress,
DTOApiToken paramApiToken)
{
// Store the final result
string strResult = "";
// Use the HttpClient
using (client)
{
// Initialize the HttpClient
client = new HttpClient();
// Create a new REST request
using (var request = new HttpRequestMessage())
{
// The Swagger page indicates this must be a "Post"
request.Method = HttpMethod.Post;
// Set the destination to the method indicated on the Swagger page
// to: api/V1/GetAuthToken
request.RequestUri = new Uri($"{APIWebAddress}api/V1/GetAuthToken");
// Convert the parameters to JavaScript Object Notation (JSON) format
var json = JsonConvert.SerializeObject(paramApiToken);
request.Content = new StringContent(json, Encoding.UTF8, "application/json");
// Make the request to the API endpoint on the ADefHelpDesk site
var response = client.SendAsync(request).Result;
// Receive the response
var JsonDataResponse =
await response.Content.ReadAsStringAsync();
// Convert the response (the JWT (Auth Token)) to a String value
strResult =
JsonConvert.DeserializeObject<string>(JsonDataResponse);
// Strip the word Bearer from the token
strResult = strResult.Replace("Bearer ", " ");
}
}
// Return the JWT
return strResult;
}
It then uses the token to call the following method to search for Help Desk Tickets:
private static async Task<DTOTaskList> SearchTasksAsync(
string APIWebAddress,
string paramBearerToken,
DTOSearchParameters paramDTOSearchParameters)
{
// Store the final result
DTOTaskList strResult = new DTOTaskList();
// Use the HttpClient
using (client)
{
// Initialize the HttpClient
client = new HttpClient();
// Create a new REST request
using (var request = new HttpRequestMessage())
{
// The Swagger page indicates this must be a "Post"
request.Method = HttpMethod.Post;
// Set the destination to the method indicated on the Swagger page
// to: api/V1/SearchTasks
request.RequestUri = new Uri($"{APIWebAddress}api/V1/SearchTasks");
// Pass the JWT in the 'header' of the request with the word "Bearer" in front
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", paramBearerToken.TrimStart());
// Convert the parameters to JavaScript Object Notation (JSON) format
var json = JsonConvert.SerializeObject(paramDTOSearchParameters);
request.Content = new StringContent(json, Encoding.UTF8, "application/json");
// Make the request to the API endpoint on the ADefHelpDesk site
var response = client.SendAsync(request).Result;
// Handle if the JWT is expired
if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized)
{
strResult.errorMessage = "Unauthorized";
return strResult;
}
// Receive the response
var JsonDataResponse =
await response.Content.ReadAsStringAsync();
// Convert the response to a String value
strResult =
JsonConvert.DeserializeObject<DTOTaskList>(JsonDataResponse);
}
}
// Return the response
return strResult;
}
When then publish the Proxy to a location that the Microsoft Flow Connector can reach such as Microsoft Azure.
The key things to keep in mind when creating a Proxy between the Microsoft Flow Custom Connector and your data source is:
- Make your code easy to call. A simple method with simple parameters is easy to integrate.
- Abstract away any complex security such as JWT tokens.
- Return a simple object, or a collection of simple objects. If you try to return nested objects you may find that Microsoft Flow will throw errors when it can’t consume the output.
Create The Custom Connector
We then open a web browser and go to: https://flow.microsoft.com and log in.
Under Data, we select Custom connectors.
We select Create custom connector, then Create from blank.
We give it a name and click Continue.
Fill in the basic information for the connector and click the Security link.
Select No authentication and click the Definition link.
Click New action.
Provide values for the General section.
Scroll down to the Request section and click the Import from sample link.
Enter values that will return data from the proxy.
In this case a query such as this would work:
https://adefhelpdeskproxy.azurewebsites.net/api/ADefHelpDesk/SearchTickets
?APIWebAddress=https%3A%2F%2Fadefhelpdesk.azurewebsites.net%2F
&userName=TestApi
&password=Password
&applicationGUID=8A4B529F-CB308BCFAC77-CB308BCFAC77
&searchText=Test
Note: The values for parameters such as APIWebAddress are URL encoded using a tool such as the one provided on the website: https://www.urlencoder.org/.
The Request section will now display the parameters in the Query section.
The values for these will be required by any Microsoft Flows that consume the Custom Connector.
Scroll down to the Response section and click the Add default response link.
This will open the Import from sample window.
Open a web browser such as the Google Chrome web browser and paste in the query, used before, into the URL box, and copy the entire response.
Note: If your query requires a http post or header values, use a tool such as Postman or Fiddler to capture the response.
Return to the Import from sample window and paste the response in the Body box and click the Import button.
The Validation section will indicate if this was successful.
Click the Create connector button to save the connector.
Consume The Custom Connector
Select My flows.
Select New, then Create from blank.
Select When a new email arrives.
Click New step.
Click Custom to switch to the Custom Connectors, then select the Custom Connector we created.
Select the SearchTickets action we created.
Fill in the parameters.
To set the searchText, click in the searchText box.
This will bring up the values gathered from the previous step[s] (in this case, the Email step), allowing us to select the email Subject.
This means that what is set as the subject of the email will be used as the search term when searching the Help Desk Tickets in the ADefHelpDesk site.
Click New step.
Search for Create HTML Table and select it from Actions.
In the Create HTML Table control, click in the From box to bring up the selector menu.
Select Body.
Next, click Show advanced options.
Customize the table.
Click New Step.
Search for, and select, Send an email.
For the To field, we select the From field from the When a new email arrives step.
This sends an email back to the email address of the person who sent the email retrieved in the first step.
For the email Body, we select the Output from the Create HTML table step.
Click Show advanced options.
Set Is HTML to yes.
Click Save.
Test The Flow
Click the Test button.
Select I’ll perform the trigger action and click Save & Test.
It will wait for you to send an email to the email account of the user account that was used to create the Flow.
Remember to put a search term in the subject of the email.
When the email is received, the flow will run.
The user who sent the email will receive an email response with the results of the Help Desk Ticket search.
Note: This is not a real world example. ADefHelpDesk API provides various methods and properties, such as a unique password for each ticket, that could be used to only return tickets for authorized users. See the ADefHelpDesk.com site and forums for more details.
Links
Microsoft Flow Documentation
Custom Connectors
Create a custom connector from scratch
AdefHelpDesk (Documentation)
Download
The project is available at http://lightswitchhelpwebsite.com/Downloads.aspx
You must have Visual Studio 2019 (or higher) installed to run the code.