Last updated on 2018-11-29
Previous Tutorial: Azure Functions – Part 5: Deploying to Azure from VSCode
Two basic and important concepts to understand in Azure Functions are Triggers and Bindings. Triggers are what case the function to execute. Bindings are a simple way to connect data with the function, be it incoming data or outgoing data. Up to now we have created functions that use HTTP triggers (that execute when an HTTP request arrives at the function’s URL), used an HTTP return value for the HTTP response, and Table storage bindings output parameter binding to store a value. In this and the following tutorials I’ll start the investigation more triggers and bindings.
Let’s begin by creating a Function App project from the wizard and in this project create a Function with an HTTP trigger. For the sake of completeness this is what the wizard creates, with some names modified:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.IO; | |
using System.Threading.Tasks; | |
using Microsoft.AspNetCore.Mvc; | |
using Microsoft.Azure.WebJobs; | |
using Microsoft.Azure.WebJobs.Extensions.Http; | |
using Microsoft.AspNetCore.Http; | |
using Microsoft.Extensions.Logging; | |
using Newtonsoft.Json; | |
namespace Vainolo.AzureFunctionsTutorial.Part6 | |
{ | |
public static class MyFunctions | |
{ | |
[FunctionName("HttpTrigger")] | |
public static async Task<IActionResult> HttpTrigger( | |
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequest req, | |
ILogger log) | |
{ | |
log.LogInformation("C# HTTP trigger function processed a request."); | |
string name = req.Query["name"]; | |
string requestBody = await new StreamReader(req.Body).ReadToEndAsync(); | |
dynamic data = JsonConvert.DeserializeObject(requestBody); | |
name = name ?? data?.name; | |
return name != null | |
? (ActionResult)new OkObjectResult($"Hello, {name}") | |
: new BadRequestObjectResult("Please pass a name on the query string or in the request body"); | |
} | |
} | |
} |
Before we continue, some basic stuff:
- the Azure Functions runtime recognizes a function as any static method in the class that has the
FunctionName
annotation. - The name of the Azure Function is defined as part of the annotation
- The name of the method is not important and doesn’t have to be the same as that of the Azure Function.
- The Function method can be synchronous or asynchronous.
- An
ILogger
parameter can be added to the function for logging to the function’s streaming logs. - The function can declare parameters that define the trigger of the function, and parameters and return values that are bind to functionality provided by the runtime.
So let’s start digging 🧐.
Every function needs to have a Trigger, otherwise it will exist but will never be invoked, which is not very useful 🥴. The trigger in this function is defined in row 17, with the HttpTrigger
annotation. The annotation includes the argument AuthorizationLevel.Anonymous
so we can call the function without any authentication, and a list of HTTP methods (get
and post
).
Just to check what happens, I created a function that does not have a trigger:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[FunctionName("NoTrigger")] | |
public static void NoTrigger(ILogger log) | |
{ | |
log.LogInformation("C# HTTP trigger function processed a request."); | |
} |
And was glad to see that the build process gives me a warning that the function is missing a trigger. Any help the build system gives is a blessing.
Let’s check another trigger: TimerTrigger
. A TimerTrigger
, obviously, triggers the function on a schedule. We define this trigger by adding a parameter of type TimerInfo
annotated with the TimerTrigger
annotation. This annotation receives as parameter either a string formatted as a CRON expression, a string formatted for a TimeSpan
, or a type that extends a TimerSchedule
. Here’s an example of the first two methods, and as a typical long-time university lecturer, I’ll leave the third one for you to figure out 😊:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// CRON formatted trigger every 5 seconds | |
[FunctionName("TimerTrigger1")] | |
public static void TimerTrigger1([TimerTrigger("*/5 * * * * *")]TimerInfo myTimer, ILogger log) | |
{ | |
log.LogInformation($"CRON trigger executed at : {DateTime.Now}"); | |
} | |
[FunctionName("TimerTrigger2")] | |
public static void TimerTrigger2([TimerTrigger("00:00:03")]TimerInfo myTimer, ILogger log) | |
{ | |
log.LogInformation($"TimeSpan trigger executed at : {DateTime.Now}"); | |
} |
Interestingly, the moment I added the TimerTrigger
and tried to run the function, it didn’t work. The runtime sait it was missing a value for AzureWebJobsStorage
. This seems weird because I don’t see the relationship between a timer and the storage, but a quick search shows that this is by design. Since I’m just playing I decide to set the value of this setting to "Dummy"
(in the local.settings.json
file), and the Function App starts and output is shown in the console every 3 and 5 just like we defined:
That’s all for today. The full list of triggers available for Azure Functions is located here if you want to investigate them by yourself. For next time I plan to check triggers based on storage like as Blob, Cosmos DB, and Queue (no trigger for Table… I wonder why). Until then, happy coding!
Next Tutorial: Azure Functions – Part 7: Blob, Queue, and Cosmos DB Triggers
Be First to Comment