Azure Functions
Azure Functions is a serverless solution that allows you to write small pieces of code that run in the cloud, without worrying about underlying infrastructure and scaling. In this article, I present what is an Azure Function and the benefits of this service, as well as how to create, debug, monitor and deploy an Azure Function using Azure Portal, Visual Studio and Visual Studio Code.
Azure Functions
As a Function as Service (FaaS), Azure Functions allows you to write code that will be invoked when some trigger is executed. This service allows developers to focus on writing code without worrying about maintaining the infrastructure.
It’s a powerful service for building microservices, automating processes and integrating with other Azure services and third-party APIs. It uses an event-driven model, where a function is invoked by a trigger.
Azure Functions offers benefits such as:
- Pay-per-use: you only pay for the resources that your functions are consuming when they are running.
- Serverless: you don’t need to worry about infrastructure.
- Automatic scaling: it can scale out or in automatically, based on the demand of your functions.
- Integration: it can easily integrate with other Azure Services (such as Azure Storage, CosmosDB, Service Bus, Event Hubs, etc) and with other third-party services (such as GitHub, etc).
- Event-driven model: functions can be invoked by a trigger.
Azure Functions fit well for a range of scenarios, they can be used for example to:
- Build a Web API
- Processing tasks, file uploads and real-time data
- Create reliable message queue systems
- Build a serverless workflow
- Respond to database changes
- Sending emails or notifications
- Run scheduled tasks
- Collect and process data from IoT devices
- Integration with order services
An Azure Function can be triggered by events such as:
- HTTP Requests: a function will be executed when an HTTP request is received.
- Timer events: a function will be executed at a scheduled time (for example, every hour, every day, etc).
- Queue events: a function will be executed when a new message is added to an Azure Storage queue.
- Changes in Azure Storage data: a function will be executed when some data is changed in Azure Storage.
A similar service in AWS for example is the AWS Lambda, and in Google Cloud Platform is the Google Cloud Functions.
[Extra] Azure Durable Functions
Azure Durable Functions might have a dedicated article just for it, but I want to explain a little bit about it before we proceed with the creation of the Azure Functions.
Azure Durable Functions is an extension of Azure Functions that allow you to write stateful functions. It lets you define stateful workflows by writing orchestrator functions and entity functions, that can control the flow of multiple stateful functions. With Durable Functions, you can simplify complex, stateful coordination requirements in serverless applications.
With Durable Functions, you can write event-driven code, and a function can wait asynchronously for one or more external events, and after that execute a series of tasks in response to these events.
There are many Application Patterns that can be used, such as: Function chaining, Fan-out/fan-in, Async HTTP APIs, Monitoring, Human Interaction and Aggregator (stateful entities).
Each of these patterns has different use cases. The Function Chaining, for example, is a sequence of functions that must be executed in a specific order (you can orchestrate functions and specify the order in which they should be executed). In this pattern, the output of one function is applied to the input of another function.
If you want to know more about Azure Durable Functions, I recommend this Microsoft’s documentation page: What are Durable Functions?
Creating an Azure Function via Azure Portal
To create an Azure Function, login into Azure Portal, and search for “Function App”:
Then click on “Create”:
Then select the following information:
For this demo, I’m using Windows, cause until this moment (February 2023), Azure Portal does not support editing functions for Linux Consumption Function Apps.
On the Hosting page, you need to select a Store Account (Azure Functions needs a Storage Account):
On Monitoring you can enable or disable Application Insights:
And then click on “Review + Create” and on the next page click on “Create”.
Now go to the “Function App” page, and you should see your function app, then click on it:
In your Function App you, in the “Functions” menu, select the “Functions” option:
And then click on “Create”:
You can choose to create the Azure Function in Azure Portal or in VS Code or some other editor. For demonstration purposes, I’m going to use the Azure Portal.
When creating your function, you can select the following options:
- Development environment: the environment where you want to create your function, you can choose “Develop in portal” (for Windows only), VS Code, or some other code editor.
- Template: It is related to your Azure Function trigger. There are many triggers that can be chosen, such as HTTP, Timer, Queue Storage, Service Bus Queue, etc.
- Function name: The name of your function
- Authorization level: Azure Function can have the following authorization level:
Anonymous
: it allows anyone to call your function without any authentication,Function
: requires a token exclusive for this function, andAdmin
: which requires the master key to be passed in the request header (this key provides unrestricted access to all functions in your app). For this example, I’m using Function.
For this example, I created a function to be trigger with HTTP, and used the authorization level “Function”:
After filling in the information you want, click on “Create”.
Note: Azure Functions created on Azure Portal can not be accessed by using Visual Studio or some other editor, and vice-versa.
On the Function page, click on “Code + test” to check the code of your function:
An Azure Function contains two main parts:
- The
run.csx
file, where we have the function code - The
function.json
file, which is where we have the function configuration
The code below is the Function App code when created with the “Develop in Portal” option (Windows OS). It will display a message with the provided “name” in case the query parameter or request body contains a name, otherwise will return a generic message:
#r "Newtonsoft.Json"
using System.Net;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives;
using Newtonsoft.Json;
public static async Task<IActionResult> Run(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;
string responseMessage = string.IsNullOrEmpty(name)
? "This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response."
: $"Hello, {name}. This HTTP triggered function executed successfully.";
return new OkObjectResult(responseMessage);
}
In the example above, the run.csx
file is selected, this is where we have the C# code for the Azure Function. Here is what is happening in the run.csx
file:
- On line 1, we are referring the external package Newtonsoft.Json, and this can be done by using the
#r <inform-package-name>
. - On lines 3 up to 6, we have the using statements to import the namespaces (similar to an ASP.NET project).
- On lines 8 up to 23, we have the method that will be invoked, when this Azure Function is triggered. Because we selected the HttpTrigger, we have the HttpRequest request object (see line 8).
In Azure Portal, you can test/run the function, you can select the file you want to see/update, and at the bottom of the page you have the “Logs”:
Note: In Azure Portal, on the “Code + Test” page you can only see the run.csx
file for functions that were created with the option to “Develop in Portal”, and for Windows OS.
The function.json
file is the configuration file for the Azure Function. In this file, you can define the function’s trigger, bindings and other configuration settings, here is a basic structure of this file:
{
"disabled":false,
"bindings":[
// ... bindings here
{
"type": "bindingType",
"direction": "in",
"name": "myParamName",
// ... more depending on binding
}
]
}
Bindings can be used for integration with other services, for example, if you have a binding of type “Service Bus”, Azure Function can add the message to the Service Bus, without you needing to create a mechanism to do that (so you don’t need to worry about how to integrate the services).
There are many types of bindings: Blbo Storage, Azure Cosmos DB, Event Grid, Event Hubs, Service Bus, etc (if you want to know more about it, check this Microsoft’s documentation page).
On the bindgins
, you can define how the input and output data are passed to and from the Azure Function. With bindings, you can access the data without needing to write additional code for it. Bindings are defined in the function’s code and can be of various types such as input bindings, output bindings, and trigger metadata bindings.
- The
type
contains the name of the binding, for example: “queueTrigger”. - The
direction
indicates whether the binding is for receiving data into the function, or for sending data from the function. For triggers, the direction is alwaysin
, input and output bindings usein
andout
, and some bindings support the special directioninout
. - The
name
is the identifier of the function, for example: “myQueue”. It is used for the bound data in the function.
Click on “Test/Run” in order to execute the function:
In the Input
page, inform the HTTP method (can be GET or POST, in this first example I’m using GET) and the query parameter and click on “Run”:
Then you should see in the Output
page the response:
And you can also see the information in the Logs:
Let’s make a new test using POST. So click on “Test/Run”, select the POST HTTP method and add a value to the “Body” and click on “Run”:
And you also should see 200 in the Output
:
And should also see the information in the Log:
Let’s now make another test, but this time using Postman. For that, click on “Get function URL”:
And copy the URL:
The URL for this function will have the following structure: https://azurefunctionsdemoblog.azurewebsites.net/api/HttpTriggerExample?code=<here-you-will-see-the-function-key>
. Then add the &name=Azure Functions
at the end of the URL, and make a GET request using Postman, with query params:
And let’s also make a POST request. For that, use the URL without the name parameter (https://azurefunctionsdemoblog.azurewebsites.net/api/HttpTriggerExample?code=<here-you-will-see-the-function-key>
), and add the JSON body to the request:
Monitoring
Azure Functions also provides a monitoring tool for your functions, where you can see the latest invocation of your functions, and you can also run queries in Application Insights to check more information. In the Azure Function page, select the “Monitor” option,
On this page you have information about success and errors while running the function, as well as the latest 20 most recent invocations of your function:
If you click on “Run query in Application Insights”, you can also check more detailed information or even query more logs in Application Insights:
Creating an Azure Functions with Visual Studio
We can also create an Azure Functions with Visual Studio, for that, in VS create a new project and search for “Azure Functions”:
Add the Azure Functions details:
In the solution, you will see a file named Function1.cs
, this is where you have your function code:
This is the function code that is automatically created:
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 HttpTriggerVisualStudioFunction
{
public static class HttpTriggerFunction
{
[FunctionName("HttpTriggerFunction")]
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] 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;
string responseMessage = string.IsNullOrEmpty(name)
? "This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response."
: $"Hello, {name}. This HTTP triggered function executed successfully.";
return new OkObjectResult(responseMessage);
}
}
}
This function has the same behaviour as the one created via Azure Portal, but contains some small differences:
- We don’t need to reference the external package with the
#r ...
, instead, we can use theusing
statement. - It contains the
HttpTrigger
attribute, with the AuthorizationLevel and the HTTP methods.
Let’s change the name of the function, for that rename your Function1.cs
file and the “FunctionName
” attribute.
To debug, add a breakpoint and start the function:
A prompt with the URL will be displayed, copy the URL:
In the browser (or using Postman), add the URL and include the ?name=<add-your-name>
and you your breakpoint will be reached:
Press F5 and get back to the browser:
To deploy it, is similar to an App Service. Right-click in the function project > Publish > select Azure > Azure Function App (Linux) (or Windows, if you are using Windows) > then select your Function App and click on “Finish”:
Then click on “Publish”:
Note: For this demo, I deleted the previous function that was created before via Azure Portal (previous topic), in order to have a clean/new environment.
Wait a few seconds and you should see your function in Azure Portal:
Get the URL and try it with Postman:
Note that because we are using Linux, we cannot edit the function code in Azure Portal, we can only see the function.jon
file:
Creating an Azure Functions with Visual Studio Code
Now let’s create an Azure Function using Visual Studio Code, for that I’m going to create a new Function App, and I’m going to select Linux as OS.
In VS Code, search for the extension “Azure Functions” and install it:
And if you are going to use C#, make sure you also have the C# extension:
After installing Azure Function extension you should see the following icon in your VS Code, click on it and click in “Sign in to Azure..”:
When you click on the sign in option, you will be redirected to a browser page to authenticate with your account. Or you can also go to View > Command Pallete:
And search and select the “Azure: Sign in” option:
Then select your subscription (in case you have a subscription but it is not visible for you, check this Microsoft’s GitHub page with information about how to solve this issue, by clicking here).
Then click on the Azure Functions icon, in the “Workspace” to create a new function:
Then select the folder where you want to create your function, and add the other requested information (similar to creating via Portal, the only difference is that you need to select the folder and a namespace):
And select the same options that was selected in the previous topic:
And you should see your function code in VS Code (the code is similar to the one created with Visual Studio):
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 HttpTriggerVSCodeFunction
{
public static class HttpTriggerFunction
{
[FunctionName("HttpTriggerFunction")]
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] 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;
string responseMessage = string.IsNullOrEmpty(name)
? "This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response."
: $"Hello, {name}. This HTTP triggered function executed successfully.";
return new OkObjectResult(responseMessage);
}
}
}
You can debug your function, for that go to the “Run and debug” button and start the function:
It will ask to install Azure Functions Core Tools, click on install:
Add a breakpoint in your code:
Copy the URL from the terminal:
In the browser (or using Postman), add the URL and include the ?name=<add-your-name>
and your breakpoint will be reached:
Press F5 and get back to the browser:
To deploy the function, click on “Deploy”:
Select Deploy to Function App:
Select the resource:
Click on Deploy:
You will receive a message saying that the deployment was completed:
Note: For this demo, I deleted the previous function that was created before via Visual Studio (previous topic), in order to have a clean/new environment.
Back to Azure Portal, you can see that the new Azure Function was deployed:
Conclusion
Azure Functions provides benefits for building serverless applications, such as automatic scalability, low costs (the costs are based on the number and time of the executions), event-driven model (a function is invoked by a trigger), support for many programming languages, are easy to deploy and integrates with other Azure Services. You can easily create your functions directly in Azure Portal (for Windows OS only), or create them with Visual Studio or Visual Studio Code, and can also Monitor the functions via Azure Portal.