Creating connectors for your Logic Apps/Flow (Part 2 – Triggers)

 

In part 1, we saw how to add regular connectors for using in Azure Logic Apps. Remember: the purpose of these blog posts is just for pointing out some gaps in the documentation you'll find on the internet.

Next to regular connectors, we can also create connectors to be used as connectors, i.e. connectors that can initiate the logic apps. There are two types of connectors : poll and push connectors. The difference in short is :

  • Poll connectors will be regularly called to see if the logic app should start, using a polling mechanism.
  • Push connectors will call the Logic app to start, using a webhook mechanism.

 

Poll triggers

As mentioned before: poll triggers will be polled on a regular interval to see if something is changed, starting the logic app when this is the case. So how is this polling working ? If you add your API app as first connector in your logic app, he'll show you your triggerfunctions. Just select your trigger, and specify a polling-interval.The triggerstate can be left blank, but will be used for keeping track of the last poll-time. What will happen now:

  1. The Logic App will poll your API app, by calling the Get-method. The triggerstate will initially be empty. The Trigger should return HTTP 202 Accepted. The triggerstate should also be returned, containing the time of calling.
  2. next polls will contain a value for the triggerstate. Here we can have two options: if we do not need to trigger (i.e. no need to start the Logic App), the App just needs to return HTTP 202 again, with no changes. If the Logic app now has to start, the app needs to return HTTP 200 OK, with a modified triggerstate, and with, of course, the information you would like to pass to the Logic App

In my case, I want to trigger the logic app, when the weather changed. The information to pass looks like this :

public class WeatherInfo
{
    public int Temperature { get; set; } = 10;
    public string WeatherCondition { get; set; } = "Stormy";
    public int ChanceOfPrecipitation { get; set; } = 80;
}

Again : on the get-function, make sure to specify what will be the output. Otherwise your output will not be usable/visible in the logic app.

[SwaggerResponse(HttpStatusCode.Accepted)]
[SwaggerResponse(HttpStatusCode.OK, "triggered", typeof(WeatherInfo))]
[SwaggerOperation("CheckWeatherReport")]

For being able to send back the information, ánd the triggerstate, I created a simple helperfunction.

private HttpResponseMessage GenerateResponse(
    HttpStatusCode code, string triggerState,
    string retryAfter, WeatherInfo data = null)
{
    HttpResponseMessage responseMessage = Request.CreateResponse(code, data);
    responseMessage.Headers.Add("location",
        $"{Request.RequestUri.Scheme}://{Request.RequestUri.Host}/api/weather?" +
        $"triggerState={HttpUtility.UrlEncode(triggerState)}");
    responseMessage.Headers.Add("retry-after", retryAfter);
    return responseMessage;
}

 

After deploying the API app to AZure (don't forget the metadata and the CORS-settings!), I add my API app to my logic app by first selecting "App Services", and then your API App.
Poll1
After that, start using your output, e.g. in a mail.

Poll2


For testing it out I created some view, that allows me to "change" the weather. If that happens, the logic apps starts working (and sends me a mail).

For completeness I'll give the full code for my API polltrigger underneath. Next time : Push triggers !!

public class WeatherController : ApiController
{
    [SwaggerResponse(HttpStatusCode.Accepted)]
    [SwaggerResponse(HttpStatusCode.OK, "triggered", typeof(WeatherInfo))]
    [SwaggerOperation("CheckWeatherReport")]
    public HttpResponseMessage Get(string triggerState = "")
    {
        if (string.IsNullOrEmpty(triggerState))
        {
            triggerState = DateTime.UtcNow.ToString();
            return GenerateResponse(HttpStatusCode.Accepted,
                triggerState, "15");
        }
        else
        {
            if (DateTime.Parse(triggerState) < DateTime.UtcNow && WeatherReport.Changed)
            {
                WeatherReport.Changed = false;
                triggerState = DateTime.UtcNow.AddMinutes(2).ToString();
                WeatherInfo info = new WeatherInfo()
                {
                    ChanceOfPrecipitation = 80,
                    Temperature = 8,
                    WeatherCondition = "Storm"
                };
                return GenerateResponse(HttpStatusCode.OK,
                    triggerState, "15", info);
            }
            else
            {
                return GenerateResponse(HttpStatusCode.Accepted,
                    triggerState, "15");
            }
        }
    }
    private HttpResponseMessage GenerateResponse(
        HttpStatusCode code, string triggerState,
        string retryAfter, WeatherInfo data = null)
    {
        HttpResponseMessage responseMessage = Request.CreateResponse(code, data);
        responseMessage.Headers.Add("location",
            $"{Request.RequestUri.Scheme}://{Request.RequestUri.Host}/api/weather?" +
            $"triggerState={HttpUtility.UrlEncode(triggerState)}");
        responseMessage.Headers.Add("retry-after", retryAfter);
        return responseMessage;
    }
}