The 3 Simplest Examples To Become An Azure Functions Master

In our last blog post, we discussed the easiest beginners guide to Azure functions. If you do not feel comfortable with Azure functions, I would recommend starting with the previous blog post and coming back to this one or reading an amazing book called Serverless computing in Azure with .NET written by  Sasha Rosenbaum or signing up for a free trial to Pluralsight. Udemy also has this awesome Azure Functions course to learn what you need to know about Azure Functions.

This blog post will take this topic one step further by looking into the most common inputs and outputs that put you on the path to use that understanding across almost all that Azure functions has to offer. To make things even more simple for now, we will do all of our development within the Azure portal. If you would like a tutorial on creating and deploying Azure functions through Visual Studio, please leave a comment below this post.

By the time you finish this tutorial, you should be an Azure functions master. As discussed in the last blog post, the reason you should consider taking the time to learn about Azure functions is Azure is on the forefront of the serverless architecture, so starting to practice with the techniques explained in this blog post can bring value to any developer looking to gain experience with Azure Functions. This blog post makes three major assumptions before beginning.

  1. You have a basic understanding of how Azure functions work
  2. You have your Azure environment set up from
  3. You have a basic understanding of the C# programming language (If not, you can always either reference The C# Player’s Guide (3rd Edition) by RB Whitaker or sign up for a free trial to Pluralsight to become familiar with C#)

This blog post will provide real-life order processing functionality and go through the following examples related to Azure functions.

  • Http Request Input/Queue Item Output/Table Storage Output
  • Queue Item Input/Blob Storage Output
  • Blob Storage Input/Email Output

Now that we have an understanding of what to expect and why this topic is worth learning, let’s get right into it.

Queue and Table Outputs

In the first Azure function example for our order processing functionality, we will require an application to send an HTTP post request with the order details in the request body as an input. If you are now asking yourself, “but what does the order details look like?” then you are already on the right track. Before we can write the code, we will need to know what the order details looks like so that we can work with this object in a meaningful manner. For the purposes of our order processing functionality, the Order class should look like this.


public class Order
{
   public string PartitionKey { get; set; }
   public string RowKey { get; set; }
   public string OrderId { get; set;}
   public string ProductId { get; set;}
   public string Email { get; set;}
   public decimal Price { get; set; }
}

If you are familiar with C#, this syntax won’t be very novel to you. We are essentially collecting some general information related to the order such as an OrderId as the primary key, ProductId to know which product was ordered, Email to know where to send the order, and Price to know how much was paid. But wait! What are the PartitionKey and Rowkey properties? We will discuss these properties later in this blog post.

Creating A Shared Class

Now that we created our order class, how do we save this class in Azure to be referenced by any of our Azure functions? What a smart question to ask. In a new browser tab, navigate to

https://yourfunctionappname.scm.azurewebsites.net

with the ‘yourfunctionappname’ being the name of your function app. After navigating to the URL, you should see something like the image below.

Azure Functions Coding Kudu Home

Now click on the Debug console dropdown in the top left corner and select CMD. You should now see a directory for your Azure functions app. In the directory, navigate to site/wwwroot. This directory is where your Azure function code will be hosted. Now click the plus sign next to the wwwroot directory name and select ‘New folder’ as shown below.

Azure Functions Coding Kudu Add Item

Create a new folder called shared. Navigate inside of the new folder called shared and do the same thing as above except select ‘New file’. Create a new file called Order.csx with the same code shown in the Order class above. We now have our shared class and the only thing left to do is reference the class within our functions.

Azure Function Code

It’s finally time to start coding our first Azure function for this functionality. If you have not set up your Azure function app yet, follow the steps in the previous Azure function tutorial blog post and come back here when finished. Don’t worry… I won’t go anywhere 😉

Let’s create a new HTTP trigger Azure function called NewOrderReceived. Within the function, copy and paste the following code into the run.csx file and replacing any boilerplate code provided by default with the function. After you replace the code, we’ll talk through the code below line-by-line.


#r "Newtonsoft.Json"
#load "..\shared\Order.csx"

using System;
using System.Net;
using Newtonsoft.Json;
public static async Task Run(HttpRequestMessage req, TraceWriter log, IAsyncCollector outputQueueItem, IAsyncCollector outputTable)
{
   <span id="mce_SELREST_start" style="overflow:hidden;line-height:0;"></span>log.Info($"Order received");

   string jsonContent = await req.Content.ReadAsStringAsync();
   var order = JsonConvert.DeserializeObject(jsonContent);
   log.Info($"Order {order.OrderId} received from {order.Email} for product {order.ProductId}");
   order.PartitionKey = "Orders";
   order.RowKey = order.OrderId;

   await outputQueueItem.AddAsync(order);
   await outputTable.AddAsync(order);

   return req.CreateResponse(HttpStatusCode.OK, new {message = $"Thank you for your order!"});<span id="mce_SELREST_end" style="overflow:hidden;line-height:0;"></span>
}

At the very beginning of the code, you will notice a ‘#r’ syntax. This syntax is used with C# Scripting to reference a library. In our case, we are referencing the Newtonsoft.Json library to parse JSON objects. Lucky for us, this library comes installed in the Azure framework since it is used so often. Lazy developers everywhere rejoice!

If you would like the best resource to learn more about writing C# Scripting code, refer to the Serverless computing in Azure with .NET book written by  Sasha Rosenbaum or signing up for a free trial to Pluralsight. I cannot recommend this book enough to learn more about what Azure functions has to offer.

The next line is using the ‘#load’ C# Scripting syntax to import our shared Order class into our NewOrderReceived function. The next three lines are our traditional C# using statements to let the class know we will be using these libraries. As we look at the Azure function header, we notice that it is public, static, asynchronous and therefore returns a Task.

Azure Function Header


public static async Task Run(HttpRequestMessage req, TraceWriter log, IAsyncCollector outputQueueItem, IAsyncCollector outputTable)

The first parameter is our HttpRequestMessage called req. This is the request coming in from the outside system. This can be in the form of a GET, POST, DELETE, HEAD, PATCH, PUT, OPTIONS, OR TRACE. Ours will be a POST, but we’ll get into that later. The second parameter is of type TraceWriter called log. This is the container we will use to log any events we want to track.

The third parameter is of type IAsyncCollector called outputQueueItem. IAsyncCollector is an object exposed in Azure to hold a collection of items that can be read and stored asynchronously. This is pretty useful when our function is asynchronous. Now, since you are a smart person, I know your next question. A collection of What? The answer is it can be a collection of anything we want!

Don’t get drunk with power just yet because I’ll explain how we assign the type of object we’re storing in the collection later. For right now, just know that for our purposes it is a collection of QueueItems.

The last parameter is another of type IAsyncCollector called outputTable. This is a collection of Azure Table Storage records. That takes care of the parameters for our function, so now let’s look at the actual code.

Azure Function Logic


log.Info($"Order received");

string jsonContent = await req.Content.ReadAsStringAsync();
var order = JsonConvert.DeserializeObject(jsonContent);
log.Info($"Order {order.OrderId} received from {order.Email} for product {order.ProductId}");
order.PartitionKey = "Orders";
order.RowKey = order.OrderId;

await outputQueueItem.AddAsync(order);
await outputTable.AddAsync(order);

return req.CreateResponse(HttpStatusCode.OK, new {message = $"Thank you for your order!"});

On the first line, you’ll notice we are using our log parameter to log some information called “Order received”. This does not provide any value to the overall functionality, but it will help us during debugging. This message will be logged within the console window so that we know this function is running. I won’t explain any of the other calls to the log.Info() method since we now know why it’s being used.

The next line reads the incoming request’s content as a string and assigns it to the jsonContent variable. Then we use the Newtonsoft.Json library to deserialize the jsonContent variable, which is just a JSON string of our Order object, and assign it to a new variable called order.

The next two lines of code are setting the PartitionKey and RowKey properties of the order variable, but why are these properties significant? In order to explain these properties, we need to begin by explaining what Azure Table Storage means.

Azure Table Storage is not necessarily NoSQL storage and not necessarily SQL storage. Azure Table Storage is broken into partitions, sort of like tables, based on a PartitionKey. Additionally, records within each partition are displayed in rows and identified through its’ RowKey property. All other data stored within the data row can be dynamic.

This provides some of the dynamic nature of NoSQL with some of the simple querying abilities of SQL. Therefore, in our function, we are setting this order record in the “Orders” partition and assigning it to a row with a key referenced by the order’s OrderId property.

The next line adds the order variable to the outputQueueItem parameter asynchronously. So… what is a QueueItem anyway? A QueueItem is an item in a queue, duh! jk. It is an item in a queue, but the reason it’s significant is that the queue is a great trigger to signal an action to fire, like… I don’t know… maybe another Azure function ¯\_(ツ)_/¯

The following line of code adds the order object to the Azure Table storage and the last line returns an HTTP response to the request to thank the user for placing the order. I think that covers the code. We can now look deeper into the definition of the Azure function.

Azure Function JSON Format

While looking at the NewOrderReceived Azure function code in the Azure portal, you’ll notice a View files tab on the right-hand side. When you click on the tab, select the function.json file. Replace the current JSON with the following code.


{
   "bindings": [
   {
      "name": "req",
      "type": "httpTrigger",
      "direction": "in",
      "methods": [
         "post"
      ],
      "route": "newpurchase",
      "webHookType": "genericJson"
   },
   {
      "name": "$return",
      "type": "http",
      "direction": "out"
   },
   {
      "type": "queue",
      "name": "outputQueueItem",
      "queueName": "ordersqueue",
      "connection": "AzureWebJobsStorage",
      "direction": "out"
   },
   {
      "type": "table",
      "name": "outputTable",
      "tableName": "Orders",
      "connection": "AzureWebJobsStorage",
      "direction": "out"
   }
   ],
   "disabled": false
}

The root of the JSON has two properties called bindings and disabled. The only thing you need to know about the disabled property is it is a boolean that can be false to enable the function and true to disable the function. All functions are enabled by default.

The Request Input Binding

The bindings property can and will likely have multiple properties below it. The first binding is made for the first parameter of our Azure function. The most important part of this binding is that the name property MUST match the name of given to the parameter.

Another required property of any binding is the “type” property. This tells Azure what kind of binding this binding is, and this one happens to be an httpTrigger type of binding. This means the value of this binding will come from an HTTP request. The last required property is the direction property.

This property’s value can be either “in” or “out”. If its’ value is set to “in” then it means it is an input binding and if it’s set to “out”… you guessed it… it means it’s an output binding.

The next property called “methods” tells Azure what type of HTTP request this Azure function will accept. Since our code is looking at the request’s content and we are expecting the request to send us a new Order object to be inserted, we are only accepting a POST request.

The “route” property is used for denoting a custom name to the function. If you have worked with web APIs or routing frameworks, this will not be new to you. Finally, the “webHookType” property is made to tell Azure what the structure is expected to be for the incoming request’s content. In this case, we are expecting there to be a JSON-formatted Order object sent to us within the request body.

The Return Output Binding (As LL Cool J said many times about returns, “don’t call it a comeback”)

The next binding is what we plan to return from the Azure function. The name we set for the binding is “$return”. The type we will return is an HTTP response since the value of the “type” property is set to “http”. As mentioned before, the “direction” property is set to “out” so we know it’s an output binding.

It’s Time To Queue The Next Parameter

The next binding has the value of the “type” property set to “queue”. This means that this parameter is an Azure queue. The name of the queue we will be creating to “queue up” the new order will be “ordersqueue”. First, we will need to create a storage account called AzureWebJobsStorage.

To add the new storage account, click on the “Storage accounts” tab on the left-hand navigation of your Azure portal. Then click the “+Add” button on the top-left of the window and enter the information for your new storage account as the example shows below.

Azure Functions Coding Storage Account

Make sure the storage account is within the same resource group as your functions and that you select a name that is acceptable. After creating the storage account, click the “Queues” tab under “Queue service” and click the “+Queue” button in the top-left corner. Enter the Queue name in the textbox as “ordersqueue” and go back to your functions app.

If you click on the Application settings link, you’ll see there is an application setting created for you called AzureWebJobsStorage with your storage account information. Now your storage account and Orders queue are set up and ready to use. This queue will actually be a trigger for our next function.

Reserving A Table For Our Orders

The last parameter called “outputTable” is an Azure table list that we will use to store the order data. We copied and pasted the JSON code in the file directly, but Microsoft doesn’t expect us to know all of the properties to set for the inputs and outputs of our functions.

If you click on the Integrate tab of your Azure function, you will see all of the inputs and outputs for the function. Updating inputs and outputs on this page are used to update the function.json code. If we did not copy and paste the function.json code, if we wanted to add our Azure table output, we would click the “+New Output” button as shown below.

Azure Functions Tutorial New Output binding

After clicking the button, set the output name to “outputTable”, table name to “Orders” and the storage account connection to our AzureWebJobsStorage connection as shown below.

Azure Functions Tutorial Select Table Storage Output binding

We just talked about what an Azure table is and how to add the output, but we still need to create the table within our storage account. To do this, go back to your storage account. Find the “Tables” tab under the Table service section and click on the tab. Click the “+Table” button in the top-left corner and enter “Orders” for the table name. After you click “OK”, you are done and WE ARE READY FOR OUR NEXT AZURE FUNCTION!

Beware Of The Blob… Storage

For our last Azure function, we consumed the order through an HTTP request and saved it to an Azure table record as well as an Azure queue record. Our next Azure function will trigger off of a new queue item and save a license file for the order inside of blob storage, but enough talk. Let’s get started!

Within your Azure functions portal, click the plus sign to add your new Azure function and select a C# Queue Triggered function. You can call your function whatever you want, but if you are out of ideas, I called mine GenerateFileToBlobStorage. I know. These names are as novel as my sense of humor. Once you add your function, replace the boilerplate code with the following code.


#load "..\shared\Order.csx"

using System;

public static void Run(Order myQueueItem, TraceWriter log, IBinder binder)
{
   log.Info($"Received an order: Order {myQueueItem.OrderId}, Product {myQueueItem.ProductId}, Email {myQueueItem.Email}");
   using (var outputBlob = binder.Bind(
   new BlobAttribute($"licenses/{myQueueItem.OrderId}.lic")))
   {
      outputBlob.WriteLine($"OrderId: {myQueueItem.OrderId}");
      outputBlob.WriteLine($"Email: {myQueueItem.Email}");
      outputBlob.WriteLine($"ProductId: {myQueueItem.OrderId}");
      outputBlob.WriteLine($"PurchaseDate: {DateTime.UtcNow}");
      var md5 = System.Security.Cryptography.MD5.Create();
      var hash = md5.ComputeHash(System.Text.Encoding.UTF8.GetBytes(myQueueItem.Email + "secret"));
      outputBlob.WriteLine($"SecretCode: {BitConverter.ToString(hash).Replace("-","")}");
   }
}

 Breaking Down The Code

Since we have broken down the parts of an Azure function in the last example, so we won’t go too deep into explaining this function. The first line imports our Order class and we will only need to use the Microsoft.System namespace.

The first parameter is the queue item that was inserted from our previous Azure function to trigger this Azure function. This method of triggering multiple Azure functions is called chaining. It’s best practice to have each of your Azure functions to only perform a single task and chain the functions to create a workflow. Following this architecture will provide the following benefits.

  1. It will aid in your functions following SOLID principles.
  2. It will make debugging and troubleshooting easier.
  3. It will prevent your functions from timing out or creating large invoice spikes (if using the consumption plan).
  4. It will promote easier reuse and maintenance.

The second parameter is our standard TraceWriter parameter to log what is happening while the function is running. The last parameter is of type IBinder called binder. The IBinder type is probably one of the most awesome types Azure has introduced. You can think of the IBinder type as a container that can hold almost any type of object.

In our case, the IBinder type will be cast into a TextWriter object to create our license file. Within the TextWriter, we are initializing a new BlobAttribute and storing it within a directory called licenses and assigning it to a variable called outputBlob.

Let’s create that blob container now. Go back to your Azure storage account and click on the Containers tab under the Blob Service section as shown below.

Azure Functions Coding Blob Container

Click the “+Container” button in the top-left and enter the name as licenses and the public access level to Private since we do not want anyone having access to these licenses. Now let’s create the JSON format for our function.

Azure JSON Structure Again

Go, once again, to your View files tab on your new Azure function and select the function.json file. Replace the current JSON in the file with the code below.

{
   "bindings": [
   {
      "name": "myQueueItem",
      "type": "queueTrigger",
      "direction": "in",
      "queueName": "ordersqueue",
      "connection": "AzureWebJobsStorage"
   },
   {
      "type": "blob",
      "name": "outputBlob",
      "path": "licenses/{rand-guid}.lic",
      "connection": "AzureWebJobsStorage",
      "direction": "out"
   }
   ],
   "disabled": false
}

The first binding is for our input Azure queue parameter and the second binding is our output IBinder parameter that creates a new blob file. Most of this JSON is self-explanatory since you already understand the properties of Azure function JSON format. I hope you are starting to get an understanding of how these inputs and outputs work for Azure functions, but let’s finish our functionality by creating one more function that will email the license file to the customer and thank them.

You’ve Got Mail… From Azure?

Our last Azure function created the blob license file, but we now need to send that file to our customer to finish the order workflow. Within your Azure functions portal, click the plus sign to add your new Azure function and select a C# Blob Triggered function as shown below. I called mine EmailFileToCustomer.

Azure Functions Tutorial Select Blob Trigger

I know it’s a little late, but I feel like I should mention that the naming of my functions in this blog post has been SUPER generic. I would like to apologize and say do not do that in your real-life applications! It is best practice to name your Azure functions as descriptively as possible since you may have many functions so finding a specific one may be difficult if they all have generic names. After creating your function, replace the default code with the following code.


#r "SendGrid"
#load "..\shared\Order.csx"

using SendGrid.Helpers.Mail;
public static void Run(string myBlob, string filename, Order ordersRow, TraceWriter log, out Mail message)
{

   var email = ordersRow.Email;
   log.Info($"Got order from {email}\n License file Name:{filename}");

   message = new Mail();
   var personalization = new Personalization();
   personalization.AddTo(new Email(email));
   message.AddPersonalization(personalization);

   Attachment attachment = new Attachment();
   var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(myBlob);
   attachment.Content = System.Convert.ToBase64String(plainTextBytes);
   attachment.Type = "text/plain";
   attachment.Filename = "license.lic";
   attachment.Disposition = "attachment";
   attachment.ContentId = "License File";
   message.AddAttachment(attachment);

   var messageContent = new Content("text/html", "Your license file is attached");
   message.AddContent(messageContent);
   message.Subject = "Thanks for your order";
   message.From = new Email("goingundercoder@gmail.org");
}

What Is That Azure Code Doing Now?

You’ll probably first notice that we need to reference the SendGrid library. You are free to use any mail server provider you like, but in my case, I decided to use SendGrid. In order to use SendGrid, you will need to sign up and get a key, but I will show you where to store that later.

We once again load our Order class in our function and add the using statement for our SendGrid library. For our first parameter, we take in the blob used to trigger this function as a string. The second string parameter with the name of filename is actually pulled from the name of the blob. We will look into how we do that a little later.

The Order parameter with the name of ordersRow is a row from our Azure table called orders for this order. We once again have our TraceWriter parameter for logging. Lastly, we have our output Mail parameter called message that will be our email to send to the customer.

In the first line of the code, we are getting the email address from the Azure table row we are being passed. The rest of the logic is simply creating an email and attaching our blob license file to the email. If you have any questions about the C# logic using the Mail library, I would suggest either looking at The C# Player’s Guide (3rd Edition) by RB Whitaker or signing up for a free trial to Pluralsight.

Adding Structure One Last Time

The JSON structure of this function is a little more involved, but you’ll see it’s still very simple once we break it down. Go to your View files tab one last time and select the function.json file. Replace the code with the code below.


{
   "bindings": [
   {
      "name": "myBlob",
      "type": "blobTrigger",
      "direction": "in",
      "path": "licenses/{filename}.lic",
      "connection": "AzureWebJobsStorage"
   },
   {
      "type": "table",
      "name": "ordersRow",
      "tableName": "Orders",
      "partitionKey": "Orders",
      "rowKey": "{filename}",
      "take": 50,
      "connection": "AzureWebJobsStorage",
      "direction": "in"
   },
   {
      "type": "sendGrid",
      "name": "message",
      "apiKey": "SendGridApiKey",
      "direction": "out"
   }
   ],
   "disabled": false
}

The first binding in the function.json file is our BlobTrigger with the name of myBlob. The one major change to what we have seen before is related to the path property. The path is pointing to our blob container, but there is a special “{filename}” key in the path. If you think back to our code, we had a parameter called filename. This key sets that parameter to the name we provided to the blob file, which happened to be the order id.

The second binding is our Azure table input with the name of ordersRow. The table name and PartitionKey are set to “Orders” and the RowKey is set to the filename parameter or order id. The take property allows us to determine the maximum number of records to take in. We used the default of 50. If you want to add it through the Integrate page, it would look like the image below.

Azure Functions Tutorial Configure Table Input

The last binding is the email output binding called message. The only difference is the apiKey property value is set to SendGridApiKey. If you were to add the output through the Integrate page, you would add the SendGrid output by clicking “+New Output” button and selecting the following on the image below.

Azure Functions Tutorial Create Email Output

The SendGridApiKey will need to be created in the AppSettings with the name of SendGridApiKey and a value of the API key SendGrid provides you to use their mail server. You can configure it output binding with the following values.

Azure Functions Tutorial Configure Email Output

Houston… We have A Working Order Processing Function

Well… we came a long way, but we finally finished our order processing Azure function workflow. To test our function workflow, all we need to do is click the Test tab on the right-hand side of the portal and enter some test post data as shown below.

Azure Functions Coding Testing

After clicking the run button to test, you should see the logging in the console as well as new rows inserted in the Azure table, a new license file in blob storage, and an email sent to the customer. If you would like more information about test-driven development (TDD) for your testing, feel free to refer back to our TDD blog post.

That officially ends this Azure function tutorial. I hope you learned a few things about Azure functions and how easy it is to build extensive workflows by linking inputs and outputs. If you are interested in Azure functions and this tutorial did not satiate your desire for everything Azure, I would suggest looking into an amazing book called Serverless computing in Azure with .NET written by  Sasha Rosenbaum or signing up for a free trial to Pluralsight. Additionally, if you want me to write more about Azure functions or agree or disagree with anything in this blog post, PLEASE COMMENT and most importantly…

Thanks For Going Undercoder With Us!

If you enjoy this blog’s content and would like to help out a developer or computer science student, feel free to   Buy Me A Coffee

The files for this blog post can be found at https://github.com/kalbert1/Azure-Function-Input-Example.

If you like the shirt below, be sure to check out our shop at https://shop.spreadshirt.com/goingundercoder.

Software Development Coder Coding Style Shirt

Advertisements

One thought on “The 3 Simplest Examples To Become An Azure Functions Master

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s