develop-azure-functions

Develop Azure Functions

In this post we are going to describe the followings:

  • The key components of a function and how they are structured
  • Create triggers and bindings to control when a function runs and where the output is directed
  • Connect a function to services in Azure
  • Create a function by using Visual Studio Code and the Azure Functions Core Tools

Explore Azure Functions development

A function contains two important pieces – your code, which can be written in a variety of languages, and some config, the function.json file. For compiled languages, this config file is generated automatically from annotations in your code. For scripting languages, you must provide the config file yourself.

The function.json file defines the function’s trigger, bindings, and other configuration settings. Every function has one and only one trigger. The runtime uses this config file to determine the events to monitor and how to pass data into and return data from a function execution. The following is an example function.json file.

{
 "disabled":false,
 "bindings":[ 
// ... bindings here 
{
 "type":"bindingType",
 "direction": "in",
 "name": "myParamName",
 // ... more depending on binding 
} 
]
 }
The bindings property is where you configure both triggers and bindings. Each binding shares a few common settings and some settings which are specific to a particular type of binding. Every binding requires the following settings:
Property Types Comments
type string Name of binding. For example, queueTrigger.
direction string Indicates whether the binding is for receiving data into the function or sending data from the function. For example, in or out.
name string The name that is used for the bound data in the function. For example, myQueue.

Function app

A function app provides an execution context in Azure in which your functions run. As such, it is the unit of deployment and management for your functions. A function app is comprised of one or more individual functions that are managed, deployed, and scaled together. All of the functions in a function app share the same pricing plan, deployment method, and runtime version. Think of a function app as a way to organize and collectively manage your functions.

Note: In Functions 2.x all functions in a function app must be authored in the same language. In previous versions of the Azure Functions runtime, this wasn’t required.

Folder structure

The code for all the functions in a specific function app is located in a root project folder that contains a host configuration file. The host.json file contains runtime-specific configurations and is in the root folder of the function app. A bin folder contains packages and other library files that the function app requires. Specific folder structures required by the function app depend on language:

Local development environments

Functions makes it easy to use your favorite code editor and development tools to create and test functions on your local computer. Your local functions can connect to live Azure services, and you can debug them on your local computer using the full Functions runtime.

The way in which you develop functions on your local computer depends on your language and tooling preferences. See Code and test Azure Functions locally for more information.

Warning: Do not mix local development with portal development in the same function app. When you create and publish functions from a local project, you should not try to maintain or modify project code in the portal.

Create triggers and bindings

Triggers are what cause a function to run. A trigger defines how a function is invoked and a function must have exactly one trigger. Triggers have associated data, which is often provided as the payload of the function.

Binding to a function is a way of declaratively connecting another resource to the function; bindings may be connected as input bindingsoutput bindings, or both. Data from bindings is provided to the function as parameters.

You can mix and match different bindings to suit your needs. Bindings are optional and a function might have one or multiple input and/or output bindings.

Triggers and bindings let you avoid hardcoding access to other services. Your function receives data (for example, the content of a queue message) in function parameters. You send data (for example, to create a queue message) by using the return value of the function.

Trigger and binding definitions

Triggers and bindings are defined differently depending on the development language.

Language Triggers and bindings are configured by…
C# class library decorating methods and parameters with C# attributes
Java decorating methods and parameters with Java annotations
JavaScript/PowerShell/Python/TypeScript updating function.json schema

For languages that rely on function.json, the portal provides a UI for adding bindings in the Integration tab. You can also edit the file directly in the portal in the Code + test tab of your function.

In .NET and Java, the parameter type defines the data type for input data. For instance, use string to bind to the text of a queue trigger, a byte array to read as binary, and a custom type to de-serialize to an object. Since .NET class library functions and Java functions don’t rely on function.json for binding definitions, they can’t be created and edited in the portal. C# portal editing is based on C# script, which uses function.json instead of attributes.

For languages that are dynamically typed such as JavaScript, use the dataType property in the function.json file. For example, to read the content of an HTTP request in binary format, set dataType to binary:

{ 
"dataType": "binary",
 "type": "httpTrigger", 
"name": "req", 
"direction": "in"
 }

Other options for dataType are stream and string.

Binding direction

All triggers and bindings have a direction property in the function.json file:

  • For triggers, the direction is always in
  • Input and output bindings use in and out
  • Some bindings support a special direction inout. If you use inout, only the Advanced editor is available via the Integrate tab in the portal.

When you use attributes in a class library to configure triggers and bindings, the direction is provided in an attribute constructor or inferred from the parameter type.

Azure Functions trigger and binding example

Suppose you want to write a new row to Azure Table storage whenever a new message appears in Azure Queue storage. This scenario can be implemented using an Azure Queue storage trigger and an Azure Table storage output binding.

Here’s a function.json file for this scenario.

{
 "bindings": [
 { 
"type": "queueTrigger",
 "direction": "in", 
"name": "order",
 "queueName": "myqueue-items",
 "connection": "MY_STORAGE_ACCT_APP_SETTING"
 }, 
{
 "type": "table",
 "direction": "out",
 "name": "$return", 
"tableName": "outTable",
 "connection": "MY_TABLE_STORAGE_ACCT_APP_SETTING"
 } 
]
 }

The first element in the bindings array is the Queue storage trigger. The type and direction properties identify the trigger. The name property identifies the function parameter that receives the queue message content. The name of the queue to monitor is in queueName, and the connection string is in the app setting identified by connection.

The second element in the bindings array is the Azure Table Storage output binding. The type and direction properties identify the binding. The name property specifies how the function provides the new table row, in this case by using the function return value. The name of the table is in tableName, and the connection string is in the app setting identified by connection.

C# script example

Here’s C# script code that works with this trigger and binding. Notice that the name of the parameter that provides the queue message content is  order  this name is required because the name property value in function.json is order .

using Microsoft.Extensions.Logging;
 using Newtonsoft.Json.Linq; // From an incoming queue message that is a JSON object, add fields and write to Table storage 
// The method return value creates a new row in Table Storage 
public static Person Run(JObject order, ILogger log) 
{
 return new Person() 
{
 PartitionKey = "Orders",
 RowKey = Guid.NewGuid().ToString(), 
Name = order["Name"].ToString(),

 MobileNumber = order["MobileNumber"].ToString()
 };
 }
 public class Person 
{
 public string PartitionKey { get; set; }
 public string RowKey { get; set; } 
public string Name { get; set; }
public string MobileNumber { get; set; } 
}

 

JavaScript example

The same function.json file can be used with a JavaScript function:

// From an incoming queue message that is a JSON object, add fields and write to Table Storage 
module.exports = async function (context, order) 
{ 
order.PartitionKey = "Orders";
 order.RowKey = generateRandomId(); 
context.bindings.order = order; 
};
 function generateRandomId()
 {
 return Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
 }

Class library example

In a class library, the same trigger and binding information — queue and table names, storage accounts, function parameters for input and output — is provided by attributes instead of a function.json file. Here’s an example:

public static class QueueTriggerTableOutput
{
    [FunctionName("QueueTriggerTableOutput")]
    [return: Table("outTable", Connection = "MY_TABLE_STORAGE_ACCT_APP_SETTING")]
    public static Person Run(
        [QueueTrigger("myqueue-items", Connection = "MY_STORAGE_ACCT_APP_SETTING")]JObject order,
        ILogger log)
    {
        return new Person() {
                PartitionKey = "Orders",
                RowKey = Guid.NewGuid().ToString(),
                Name = order["Name"].ToString(),
                MobileNumber = order["MobileNumber"].ToString() };
    }
}

public class Person
{
    public string PartitionKey { get; set; }
    public string RowKey { get; set; }
    public string Name { get; set; }
    public string MobileNumber { get; set; }
}

Additional resource

For more detailed examples of triggers and bindings please visit:

Connect functions to Azure services

Your function project references connection information by name from its configuration provider. It does not directly accept the connection details, allowing them to be changed across environments. For example, a trigger definition might include a connection property. This might refer to a connection string, but you cannot set the connection string directly in a function.json. Instead, you would set connection to the name of an environment variable that contains the connection string.

The default configuration provider uses environment variables. These might be set by Application Settings when running in the Azure Functions service, or from the local settings file when developing locally.

Connection values

When the connection name resolves to a single exact value, the runtime identifies the value as a connection string, which typically includes a secret. The details of a connection string are defined by the service to which you wish to connect.

However, a connection name can also refer to a collection of multiple configuration items. Environment variables can be treated as a collection by using a shared prefix that ends in double underscores __. The group can then be referenced by setting the connection name to this prefix.

For example, the connection property for a Azure Blob trigger definition might be Storage1. As long as there is no single string value configured with Storage1 as its name, Storage1__serviceUri would be used for the serviceUri property of the connection. The connection properties are different for each service.

Configure an identity-based connection

Some connections in Azure Functions are configured to use an identity instead of a secret. Support depends on the extension using the connection. In some cases, a connection string may still be required in Functions even though the service to which you are connecting supports identity-based connections.

 Note: Identity-based connections are not supported with Durable Functions.

When hosted in the Azure Functions service, identity-based connections use a managed identity. The system-assigned identity is used by default, although a user-assigned identity can be specified with the credential and clientID properties. When run in other contexts, such as local development, your developer identity is used instead, although this can be customized using alternative connection parameters.

Grant permission to the identity

Whatever identity is being used must have permissions to perform the intended actions. This is typically done by assigning a role in Azure RBAC (role-based access control) or specifying the identity in an access policy, depending on the service to which you are connecting.

Important: Some permissions might be exposed by the target service that are not necessary for all contexts. Where possible, adhere to the

Create an Azure Function by using Visual Studio Code

In this part we are going to show how to create a simple C# function that responds to HTTP requests. After creating and testing the code locally in Visual Studio Code you will deploy to Azure.

Prerequisites

Before you begin make sure you have the following requirements in place:

Create your local project

In this section, we use Visual Studio Code to create a local Azure Functions project in C#. After  we’ll publish this function code to Azure.

  1. Open VS Code and then choose the Azure icon in the Activity bar, then in the Workspace area, press to + and finally, select Create Function….
develop-azure-functions-1.png
start VS code to create Azure function

when you press create Function then q  pop-up message will likely appear prompting you to create a new project, if it does select Create new project.

  1. Choose a directory location for your project workspace and choose Select.

     Note

    Be sure to select a project folder that is outside of an existing workspace.

  2. Provide the following information at the prompts:
    • Select a language: Choose C#.
    • Select a .NET runtime: Choose .NET 6
    • Select a template for your project’s first function: Choose HTTP trigger.
    • Provide a function name: Type HttpExample.
    • Provide a namespace: Type My.Function.
    • Authorization level: Choose Anonymous, which enables anyone to call your function endpoint.
    • Select how you would like to open your project: Choose Add to workspace.

Using this information, Visual Studio Code generates an Azure Functions project with an HTTP trigger, as following:

develop-azure-functions-2.png
generate Function code

Project structure:

Azure function project

The generated files (classes)  are as follow:

Project file: Function.csproj:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net6.0</TargetFramework>
    <AzureFunctionsVersion>v4</AzureFunctionsVersion>
    <RootNamespace>Azure_Function</RootNamespace>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Microsoft.Azure.WebJobs.Extensions.OpenApi" Version="1.0.0" />
    <PackageReference Include="Microsoft.NET.Sdk.Functions" Version="4.1.1" />
  </ItemGroup>
  <ItemGroup>
    <None Update="host.json">
      <ToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </None>
    <None Update="local.settings.json">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      <CopyToPublishDirectory>Never</CopyToPublishDirectory>
    </None>
  </ItemGroup>
</Project>
MyFunction.cs:
using System.IO;
using System.Net;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Attributes;
using Microsoft.Extensions.Logging;
using Microsoft.OpenApi.Models;
using Newtonsoft.Json;
namespace My.Function
{
    public class MyFunction
    {
        private readonly ILogger<MyFunction> _logger;
        public MyFunction(ILogger<MyFunction> log)
        {
            _logger = log;
        }
        [FunctionName("MyFunction")]
        [OpenApiOperation(operationId: "Run", tags: new[] { "name" })]
        [OpenApiParameter(name: "name", In = ParameterLocation.Query, Required = true, Type = typeof(string), Description = "The **Name** parameter")]
        [OpenApiResponseWithBody(statusCode: HttpStatusCode.OK, contentType: "text/plain", bodyType: typeof(string), Description = "The OK response")]
        public async Task<IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req)
        {
            _logger.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);
        }
    }
}

Extensions.json:

{
  "recommendations": [
    "ms-azuretools.vscode-azurefunctions",
    "ms-dotnettools.csharp"
  ]
}

 host.json:

{
    "version": "2.0",
    "logging": {
        "applicationInsights": {
            "samplingSettings": {
                "isEnabled": true,
                "excludedTypes": "Request"
            }
        }
    }
}

Settings.json:

{
  "azureFunctions.deploySubpath": "bin/Release/net6.0/publish",
  "azureFunctions.projectLanguage": "C#",
  "azureFunctions.projectRuntime": "~4",
  "debug.internalConsoleOptions": "neverOpen",
  "azureFunctions.preDeployTask": "publish (functions)"
}

Run the function locally

Visual Studio Code integrates with Azure Functions Core tools to let you run this project on your local development computer before you publish to Azure.

  1. Make sure the terminal is open in Visual Studio Code. You can open the terminal by selecting Terminal and then New Terminal in the menu bar.
  2. Press F5 to start the function app project in the debugger. Output from Core Tools is displayed in the Terminal panel. Your app starts in the Terminal panel. You can see the URL endpoint of your HTTP-triggered function running locally.
develop-azure-functions-3-1.png
Running Functions on VS code Terminal after pressing to F%
develop-azure-functions/media/run-function-local.png
The endpoint of your HTTP-triggered function is displayed in the **Terminal** panel.

With Core Tools running, go to the Azure: Functions area. Under Functions, expand Local Project > Functions. Right-click the MyFunction Http  and choose and  Execute Function Now as following:

develop-azure-functions-4.png
Execute Function on VS Code

In Enter request body type the request message body value of { "name": "Azure" } ex replace Azure to Mehrdad and Press Enter to send this request message to your function. When the function executes locally and returns a response, a notification is raised in Visual Studio Code. Information about the function execution is shown in Terminal panel. as following:

Executed function "MyFunction". Response: "Hello, Mehrdad. This HTTP triggered function executed successfully."

open browser and type the address:http://localhost:7071/api/swagger/ui

give a value for parameter name (e.g. Mehrdad instead of Azure) and execute.

develop-azure-functions-5-3.png
Azure Function Swagger UI

As you see from the UI functions is executed.

Press Shift + F5 to stop Core Tools and disconnect the debugger.

After you’ve verified that the function runs correctly on your local computer, it’s time to use Visual Studio Code to publish the project directly to Azure.

Sign in to Azure

Before you can publish your app, you must sign in to Azure. If you’re already signed in, go to the next section.

  1. If you aren’t already signed in, choose the Azure icon in the Activity bar, then in the Azure: Functions area, choose Sign in to Azure….
  2. When prompted in the browser, choose your Azure account and sign in using your Azure account credentials.
  3. After you’ve successfully signed in, you can close the new browser window. The subscriptions that belong to your Azure account are displayed in the Side bar.

Create resources in Azure

In this section, you create the Azure resources you need to deploy your local function app.

  1. Choose the Azure icon in the Activity bar, then in the Resources area select the Create resource… button.
  2. Provide the following information at the prompts:
    • Select Create Function App in Azure…
    • Enter a globally unique name for the function app: Type a name that is valid in a URL path. The name you type is validated to make sure that it’s unique in Azure Functions (e.g. MehFunctionApp).
    • Select a runtime stack: Use the same choice you made in the Create your local project section above. (e.g. .NET 6)
    • Select a location for new resources: For better performance, choose a region near you (e.g. West Europe).
    • Select subscription: Choose the subscription to use. You won’t see this if you only have one subscription.

    The extension shows the status of individual resources as they are being created in Azure in the AZURE: ACTIVITY LOG area of the terminal window.

  3. When completed, the following Azure resources are created in your subscription, using names based on your function app name: (MehFunctionApp) 
    • A resource group, which is a logical container for related resources.
    • A standard Azure Storage account, which maintains state and other information about your projects.
    • A consumption plan, which defines the underlying host for your serverless function app.
    • A function app, which provides the environment for executing your function code. A function app lets you group functions as a logical unit for easier management, deployment, and sharing of resources within the same hosting plan.
    • An Application Insights instance connected to the function app, which tracks usage of your Serverless function.

Even with login to Azure portal then you can see all information regarding to you FunctionApp: MehFunctionApp as shown in the following figure:

develop-azure-functions-9.png
MehFunctionApp

Deploy the code

  1. In the WORKSPACE section of the Azure bar select the Deploy… button, and then select Deploy to Function App….
  2. When prompted to Select a resource, choose the function app you created in the previous section. (MehFunctionApp: Resouce mehfunctionapp2)
  3. Confirm that you want to deploy your function by pressing to  Deploy button on the confirmation prompt as following figure:/develop-azure-functions-11.png

Important: Publishing to an existing function overwrites any previous deployments.

Run the function in Azure

  1. Back in the Resources area in the side bar, expand your subscription, your new function app, and FunctionsRight-click the HttpExample function and choose Execute Function Now….

    develop-azure-functions-12-2.png
    Execute Function
  2. In Enter request body you see the request message body value of { "name": "Azure" }. Press Enter to send this request message to your function.
  3. When the function executes in Azure and returns a response, a notification is raised in Visual Studio Code.

    develop-azure-functions-13.png
    Enter Request body

Test Function App in Azure Portal

login to the Azure portal and press to  the All Resources and then to the MehFunctionApp then you can see the following figure:
develop-azure-functions-14.png
Test of function in Azure Portal
Test by pressing to Stop and then  to Start button.
Press to the Brose button then you can see the following:
As you see in  the above figure:
Functions 4.0 app is up and running Azure Functions is an event-based Serverless compute experience to accelerate your development.

Clean up

Clean up and delete Function app via Visual Studio code :
find the Azure Explorer’s Functions section, right-click on the Function app and select Delete Function App. In the pop-up window, and confirm the deletion, as shown in the following image:
develop-azure-functions-16.png
Clean up in Visual Studio
The other resources shall be cleaned up via Azure Portal.

Adding Source code to  Remote Git repository Github.

First we should login to the Github from VS code if we have note done before.

We can create Git repository for our FunctionApp : Azure-Function (local folder name) fram VS code as following:

  1.  click on the Source control icon on  the left side bar, then you see the commit
  2.  press on the commit to Commit Changes:
develop-azure-functions-17.png
Adding Source code to  Remote Git repository Github.
develop-azure-functions-18.png
No Staged changed

3- Then a popup shall be displayed as following:

Asking you : to  stage all….

4- press to the Yes button the you can see the following image:

develop-azure-functions-19.png
Publish Bhranch

5- press to the Publish Branch button then asks you to choose a private or public Repository on Github as following image:

develop-azure-functions-20.png
Choose of Repository type

6- Choose one of them then project Azure- Function is published to the Github as : mehzan07/Aure-Functios and in the down right of VS code shows process is succeed. and VS Code shows as following:

develop-azure-functions-21.png
Sync on Changes

7- go to the Github account mehzan07 then you can see the Remote repository : mehzan07 /Azure-Function as follow:

develop-azure-functions-22.png
Code on Github

you can find source code in my Github

Conclusion

In this post I have created  Azure Function . NET 6  in the VS code locally and tested it.  Then  Deployed it to Azure portal and tested it in the both environment. And in the end I have Created remote repository on Github via VS Code.

In my next post I will describes Create Azure Function App in .NET C# and Deploy to Azure

This post is part of “Azure step by step 

Back to home page