Azure Functions Labs – Information and setup instructions

I started my learning of Azure Functions, I.e. Service-less computing by writing this .NET Core Console application which calls the following Azure Functions each with a different trigger type. I hosted the console application on GitHub here. You will need the .NET Core runtime installed on your work station to run the console app, check this out.

Labs

Before beginning the following labs, be sure to complete the Getting Started section further down in this article.

Lab Name Lab Location Details
Lab 1: Azure Functions – Blob Storage Lab 1, Lab 1.1 Blob Storage
Lab 2: Azure Functions – Cosmos DB Lab 2, Lab 2.1, Lab 2.2 Cosmos DB
Lab 3: Azure Functions – Event Grid Event Grid
Lab 4: Azure Functions – Event Hub Lab 4, Lab 4.1 Event Hubs
Lab 5: Azure Functions
Lab 6: Azure Functions
Lab 7: Azure Functions – HTTP trigger Lab 7, Lab 7.1, Lab 7.2 HTTP Triggers
Lab 8: Azure Functions – Microsoft Graph Lab 8 Microsoft Graph
Lab 9: Azure Functions
Lab 10: Azure Functions
Lab 11: Azure Functions – Storage Queue Lab 11 Storage Queue
Lab 12: Azure Functions – SendGrid
Lab 13: Azure Functions – Service Bus Lab 13, Lab 13.1 Service Bus
Lab 14: Azure Functions – SignalR
Lab 15: Azure Functions – Table Storage
Lab 16: Azure Functions – Timer Lab 16, Lab 16.1 Timer trigger
Lab 17: Azure Functions
Lab 18: Durable Functions
Lab 19: Binding expressions and patterns Patterns

NOTE: For all of the trigger types an endpoint is a requirement. An endpoint, in generic terms, is nothing more than a accessible unique identifier that is used trigger code.

.NET Framework vs. .NET Core Framework

Did you know Azure Functions 1.x runs(ran) with .NET Framework and 2.x runs with the .NET Core Framework

Azure Functions languages

Although these labs focus mostly on C#, because that is my favorite, you can write Azure Functions in many languages. See the list here.

Host.json

To be an expert in regards to Azure Functions, you need to know all the attributes and configurations possible for a Function App. Read about them here “host.json reference for Azure Functions”. Note that the host.json file lives in the wwwroot directory of the Function App and is therefore a logical conclusion that changes to that file impact the Function App, I.e. not only the function. There is a function.json file which can be used to make function specific configurations. You must also recognize, perfect and understand the specific configurations per binding type. Each trigger type has some unique settings, like:

  • maxBatchSize, prefetchCount, batchCheckpointFrequency
  • GatewayMode, Protocol, leasePrefix
  • and many, many more…

Bindings and integrations

Bindings in Azure Functions 1.0 were native which made them hard to update (.NET Framework 4.6). It was difficult because the native bindings were bound to the runtime and making a change to the binding required a change to the runtime. With Azure Function 2.0 (.NET Standard 2.0) the bindings can be versioned independent of the runtime and are developed separately. This means each team can develop capabilities at their own pace. Here is a list of Azure Function v2 bindings:

  • HTTP
  • Timer
  • Microsoft.Azure.WebJobs.Extensions.Storage
  • Microsoft.Azure.WebJobs.Extensions.ServiceBus
  • Microsoft.Azure.WebJobs.Extensions.EventHubs
  • Microsoft.Azure.WebJobs.Extensions.CosmosDB
  • Microsoft.Azure.WebJobs.Extensions..EventGrid
  • Microsoft.Azure.WebJobs.Extensions.MicrosoftGraph
  • Microsoft.Azure.WebJobs.Extensions.DurableTask
  • Microsoft.Azure.WebJobs.Extensions.SignalRService When you create a trigger using one of the above types, you are prompted to install the required extension for the selected binding. Something similar to that shown in Figure 1.

image

  • The source code for the extensions is here.
  • The list of supported bindings are here.
  • See here to compare messaging services.

TIP: If you ever need to install an extension manually, add the extension to the extensions.csproj file and run the following command in KUDU/SCM.

dotnet build extensions.csproj -o bin --no-incremental --packages D:\home\.nuget

Declarative vs. Imperative Azure Functions

By default, Azure Functions use a declarative binding pattern that utilizes the function.json configuration file to define both input and output binding definitions. For example, a default declarative binding pattern for an HTTP Triggered Azure Functions is similar to the following. It includes the authLevel, the name of the input parameter passed into the Azure Function Run() method and the direction, etc.

{
   "bindings": [
     {
       "authLevel": "anonymous",
       "name": "req",
       "type": "httpTrigger",
       "direction": "in",
       "methods": [
         "get"
       ]
     },
     {
       "name": "$return",
       "type": "http",
       "direction": "out"
     }
   ],
   "disabled": false
}

With an HTTP Triggered Azure Function there is also a default output binding that returns the Task to the client that triggered the Azure Function. An Event Hub or Blob Trigger Azure Function, for example, do not have a default output binding. You can add additional inputs or outputs for an Azure Function using the portal, Figure 2, or if you know the pattern you can update the json file directly, Manually making the change to the json file via the portal can lead the issue I discussed here.

image

If there is a need to add an additional output binding for a Blob Storage account, then the function.json file would be updated to include this snippet. It includes the type, the name of the output parameter that I can reference from the parameters in the Run() method, the direction and some others…

{
       "type": "blob",
       "name": "outputBlob",
       "path": "test/{rand-guid}",
       "connection": "AzureWebJobsDashboard",
       "direction": "out"
}

Now, onto imperative. Think of the difference between Declarative and Imperative in the same way you think about design-time vs. runtime. When you know from the beginning which combination of bindings the Azure Function requires, then create them declaratively, however, if, based on the processing of the input to the Azure Function, the output binding can have different endpoints, then imperative binding is necessary. The way you imperatively (or at runtime) define bindings for an Azure Function is by passing the Binder input parameter into the Run() method of the Azure Function, similar to the following.

Run(string input, Binder binder)

Then, within the Run() method, you can use the BindAsync() method to dynamically create the output binding and utilize it. For example, if instead of the outputBlob writing to path “test/” (which was declared declaratively) that can be identified at runtime, as shown in the following snippet.

public static async Task Run(string input, string name, Binder binder, TraceWriter log)
{
     string path = $"coolcontainer\{name}";
     var attributes = new Attribute[]
     {   
         new BlobAttribute(path),
         new StorageAccountAttribute("")
     };
     using (var writer = await binder.BindAsync(attributes))
     {
         writer.Write(input);
     }
}

NOTE: do not declaratively declare an output binding if you plan to define them imperatively in the code. Here are more links that can add more details about runtime descriptions of out bound triggers.

NOTE: I am actually leaning for towards using the client libraries for outbound triggers instead of the Binder approach. Let’s see how this progresses over time.

Inbound vs. Outbound triggers

All Function Apps cannot create all outbound types of connections…

image

Dedicated vs. Consumption vs. Premium

The full description is here “Azure Functions scale and hosting” and will therefore not recover it. NOTE: In the article, dedicated is often referred to as App Service plan. In summary, when you run an Azure Function App, which can contain many Azure Functions in the dedicated plan, it is not ‘really’ server-less because you are running it in an App Service Plan which you have already created, this is useful, however, when your Azure Function App needs more than 1.5GB of memory for example, you can also enable AlwaysOn and avoid any startup latencies. Additionally, on a dedicated plan you are not limited to 5 or 10 minute execution times. Running an Azure Function App in consumption mode is truly server-less, meaning, after a given amount of time where the your Azure Function is not used, the VM will be de-configured and returned to the pool of available resources. When the Azure Function needs to run again, the VM will come back on-line and run. You pay only for the time in which the code it executing. So super awesome!

Getting Started

Create a Function App. To complete the labs, you will need an Azure Function App. It is assumed you already have an Azure Subscription and understand the concepts of Resource Groups, App Service Plans and the difference between a Dedicated versus Consumption based Azure Function App, oh…and the difference between an Azure Function App and an Azure Function would also be good to know…

Creating an Azure Function App

Login to the Azure portal and click the +Create a resource link on the top left of the page. Search for ‘Function App’ and then select the Function App, as seen in Figure 3. There is also some nice information here “Create your first function in the Azure portal”.

image

Enter the required details for creating the Azure Function App, similar to that seen in Figure 4. The App name must be unique as it is a global, internet accessible endpoint. For these labs I recommend you create a new Resource Group. I recommend that because once you are finished with these labs, you know which resources you created while working them and can delete them all once you finish. Windows OS, and chose a Consumption Plan, Hosting Plan based Azure Function App for the labs but I cannot think of a reason why any of the labs wouldn’t work in dedicated or premium mode.

image

For Location, pick the one closest to you or, in a real situation, close to your customers/users. Make sure both Storage and Application Insights are in the same region as Location. I have created one Storage account for all the Azure Function Apps, I have not seen any negatives of doing that. Again, be sure to have the storage in the same region as the Azure Function App for performance reasons. NOTE: AFAIK there is no logic in the portal that puts a lock on or link between the Azure Function App and the selected storage account. If you, for some reason, perhaps when you are going through your subscription resources, looking for resources to delete, you remove the storage account, you destroy all the Azure Function you have built, there is no recovery. This is why I have 1 storage account for all Azure Function Apps and I also give it a recognizable name…

Click the Create button to create the Azure Function App. Done! Once created, you are ready to begin the labs.