When you buy this book you support this site! - Thank You for your support!

Apr 23

Written by: Michael Washington
4/23/2019 8:13 PM  RssIcon

image

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.

image

The overall application flow looks like this:

  1. The user sends an Email to Microsoft Office account with the search term in the Subject field of the Email
  2. Microsoft Flow is triggered and invokes the Custom Connector to search the tickets in the ADefHelpDesk site
  3. The Microsoft Flow formats the response into an HTML table and sends an Email response to the user 

 

The User Experience

image

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.

image

The Microsoft Flow kicks off, triggered by the Email.

image

This kicks off the Microsoft Flow step that invokes the Custom Connector to search the Help Desk Tickets in the ADefHelpDesk site.

image

The Microsoft Flow then formats that response into an HTML table and sends an Email back to the user.

 

Setting Up the ADefHelpDesk API

image

You can download and install ADefHelpDesk from the site at: http://ADefHelpDesk.com.

image

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.

image

You will need to copy the information on the Connection Information tab, for the API account, to use later.

image

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

image

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.

 

image

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;
        }

 

image

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

image

We then open a web browser and go to: https://flow.microsoft.com and log in.

image

Under Data, we select Custom connectors.

image

We select Create custom connector, then Create from blank.

image

We give it a name and click Continue.

image

Fill in the basic information for the connector and click the Security link.

image

Select No authentication and click the Definition link.

image

Click New action.

image

Provide values for the General section.

image

Scroll down to the Request section and click the Import from sample link.

image

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/.

 

image

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.

image

Scroll down to the Response section and click the Add default response link.

image

This will open the Import from sample window.

image

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.

image

Return to the Import from sample window and paste the response in the Body box and click the Import button.

image

The Validation section will indicate if this was successful.

image

Click the Create connector button to save the connector.

 

Consume The Custom Connector

image

Select My flows.

image

Select New, then Create from blank.

image

Select When a new email arrives.

image

Click New step.

image

Click Custom to switch to the Custom Connectors, then select the Custom Connector we created.

image

Select the SearchTickets action we created.

image

Fill in the parameters.

image

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.

image

Click New step.

image

Search for Create HTML Table and select it from Actions.

image

In the Create HTML Table control, click in the From box to bring up the selector menu.

Select Body.

image

Next, click Show advanced options.

image

Customize the table.

image

Click New Step.

image

Search for, and select, Send an email.

image

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.

image

For the email Body, we select the Output from the Create HTML table step.

image

Click Show advanced options.

image

Set Is HTML to yes.

image

Click Save.

 

Test The Flow

image

Click the Test button.

image

Select I’ll perform the trigger action and click Save & Test.

image

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.

image

When the email is received, the flow will run.

image

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.


Your name:
Gravatar Preview
Your email:
(Optional) Email used only to show Gravatar.
Your website:
Title:
Comment:
Security Code
CAPTCHA image
Enter the code shown above in the box below
Add Comment   Cancel 
Microsoft Visual Studio is a registered trademark of Microsoft Corporation / LightSwitch is a registered trademark of Microsoft Corporation