You are currently viewing Introduction to Azure Functions

Introduction to Azure Functions

Azure Functions is a serverless compute service that enables you to run event-driven code without having to explicitly provision or manage infrastructure. It’s part of Microsoft’s Azure cloud platform and offers a range of benefits, including automatic scaling, integrated security, and the ability to pay only for what you use.

Key Benefits of Azure Functions

  1. Serverless Architecture: No need to manage infrastructure. Simply deploy your code and Azure handles the rest.
  2. Scalability: Automatically scales up or down based on the demand.
  3. Cost-Efficient: Pay only for the compute resources you use.
  4. Language Support: Supports multiple languages, including C#, JavaScript, Python, and more.
  5. Integrated Security: Provides built-in security features to help protect your applications.

Getting Started with Azure Functions

Prerequisites

  • Azure Subscription: You’ll need an active Azure subscription. You can create a free account if you don’t have one.
  • Azure Functions Core Tools: Install the Azure Functions Core Tools to create, debug, and deploy your functions locally.
  • Integrated Development Environment (IDE): Use an IDE like Visual Studio Code for development.

Creating Your First Azure Function

  1. Set Up Your Development Environment:
  • Install Visual Studio Code.
  • Install the Azure Functions extension for Visual Studio Code.
  • Install the Azure Functions Core Tools.
  1. Create a New Function App:
  • Open Visual Studio Code.
  • Select Azure from the Activity Bar.
  • Click Create New Project and follow the prompts to set up your project.
  1. Choose a Template:
  • Select a trigger type. For example, HTTP trigger, Timer trigger, Blob trigger, etc.
  • Configure the function by providing a name and namespace.
  1. Develop Your Function:
  • Write the code for your function. For an HTTP trigger, you might write something like:
   using System.IO;
   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;

   public static class HttpExample
   {
       [FunctionName("HttpExample")]
       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;

           return name != null
               ? (ActionResult)new OkObjectResult($"Hello, {name}")
               : new BadRequestObjectResult("Please pass a name on the query string or in the request body");
       }
   }
  1. Run and Test Locally:
  • Use the Azure Functions Core Tools to run your function locally.
  • Test it using tools like Postman or curl.
  1. Deploy to Azure:
  • Use the Azure Functions extension in Visual Studio Code to deploy your function to Azure.

Real-Time Use Case: Building a Serverless REST API

Scenario

Let’s build a serverless REST API for a simple to-do application. Users can add, retrieve, update, and delete to-do items. We will use Azure Functions to handle the API requests and Azure Table Storage to store the to-do items.

Step-by-Step Implementation

Step 1: Set Up Azure Table Storage

  1. Create a Storage Account:
  • Go to the Azure portal.
  • Create a new Storage Account.
  1. Create a Table:
  • In the Storage Account, create a new table named ToDoItems.

Step 2: Create the Azure Function App

  1. Create a New Project:
  • In Visual Studio Code, create a new Azure Functions project.
  1. Add Functions for CRUD Operations:
  • Create HTTP-triggered functions for each operation: Create, Read, Update, and Delete.

Step 3: Implement the Functions

  1. Create To-Do Item:
  • Create a function named CreateToDoItem:
   public static class CreateToDoItem
   {
       [FunctionName("CreateToDoItem")]
       public static async Task<IActionResult> Run(
           [HttpTrigger(AuthorizationLevel.Function, "post", Route = "todo")] HttpRequest req,
           [Table("ToDoItems", Connection = "AzureWebJobsStorage")] IAsyncCollector<ToDoItem> toDoTable,
           ILogger log)
       {
           log.LogInformation("Creating a new ToDo item.");

           string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
           ToDoItem input = JsonConvert.DeserializeObject<ToDoItem>(requestBody);

           if (input == null || string.IsNullOrEmpty(input.TaskDescription))
           {
               return new BadRequestObjectResult("Invalid ToDo item.");
           }

           ToDoItem toDoItem = new ToDoItem
           {
               PartitionKey = "ToDo",
               RowKey = Guid.NewGuid().ToString(),
               TaskDescription = input.TaskDescription,
               IsCompleted = false
           };

           await toDoTable.AddAsync(toDoItem);

           return new OkObjectResult(toDoItem);
       }
   }
  1. Retrieve To-Do Items:
  • Create a function named GetToDoItems:
   public static class GetToDoItems
   {
       [FunctionName("GetToDoItems")]
       public static async Task<IActionResult> Run(
           [HttpTrigger(AuthorizationLevel.Function, "get", Route = "todo")] HttpRequest req,
           [Table("ToDoItems", Connection = "AzureWebJobsStorage")] CloudTable toDoTable,
           ILogger log)
       {
           log.LogInformation("Getting ToDo items.");

           TableQuery<ToDoItem> query = new TableQuery<ToDoItem>().Where(TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, "ToDo"));
           var result = await toDoTable.ExecuteQuerySegmentedAsync(query, null);

           return new OkObjectResult(result.Results);
       }
   }
  1. Update To-Do Item:
  • Create a function named UpdateToDoItem:
   public static class UpdateToDoItem
   {
       [FunctionName("UpdateToDoItem")]
       public static async Task<IActionResult> Run(
           [HttpTrigger(AuthorizationLevel.Function, "put", Route = "todo/{id}")] HttpRequest req,
           [Table("ToDoItems", Connection = "AzureWebJobsStorage")] CloudTable toDoTable,
           string id,
           ILogger log)
       {
           log.LogInformation("Updating ToDo item.");

           string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
           ToDoItem input = JsonConvert.DeserializeObject<ToDoItem>(requestBody);

           if (input == null || string.IsNullOrEmpty(input.TaskDescription))
           {
               return new BadRequestObjectResult("Invalid ToDo item.");
           }

           TableOperation retrieveOperation = TableOperation.Retrieve<ToDoItem>("ToDo", id);
           TableResult retrievedResult = await toDoTable.ExecuteAsync(retrieveOperation);

           if (retrievedResult.Result == null)
           {
               return new NotFoundObjectResult("ToDo item not found.");
           }

           ToDoItem toDoItem = (ToDoItem)retrievedResult.Result;
           toDoItem.TaskDescription = input.TaskDescription;
           toDoItem.IsCompleted = input.IsCompleted;

           TableOperation updateOperation = TableOperation.Replace(toDoItem);
           await toDoTable.ExecuteAsync(updateOperation);

           return new OkObjectResult(toDoItem);
       }
   }
  1. Delete To-Do Item:
  • Create a function named DeleteToDoItem:
   public static class DeleteToDoItem
   {
       [FunctionName("DeleteToDoItem")]
       public static async Task<IActionResult> Run(
           [HttpTrigger(AuthorizationLevel.Function, "delete", Route = "todo/{id}")] HttpRequest req,
           [Table("ToDoItems", Connection = "AzureWebJobsStorage")] CloudTable toDoTable,
           string id,
           ILogger log)
       {
           log.LogInformation("Deleting ToDo item.");

           TableOperation retrieveOperation = TableOperation.Retrieve<ToDoItem>("ToDo", id);
           TableResult retrievedResult = await toDoTable.ExecuteAsync(retrieveOperation);

           if (retrievedResult.Result == null)
           {
               return new NotFoundObjectResult("ToDo item not found.");
           }

           ToDoItem toDoItem = (ToDoItem)retrievedResult.Result;
           TableOperation deleteOperation = TableOperation.Delete(toDoItem);
           await toDoTable.ExecuteAsync(deleteOperation);

           return new OkObjectResult("ToDo item deleted.");
       }
   }

Testing the API

Use tools like Postman to test the API. You can make requests to the endpoints to create, retrieve, update, and delete to-do items.

Best Practices for Securing Azure Functions

  1. Use Managed Identities:
  • Enable Managed Identities for your Azure Function to securely access other Azure services without storing credentials.
  1. Implement API Keys and Tokens:
  • Use API keys or tokens for authenticating and authorizing API requests.

3.

Enable HTTPS:

  • Always use HTTPS to encrypt data in transit.
  1. Use Application Insights:
  • Monitor your functions using Application Insights to detect and diagnose issues quickly.
  1. Restrict Network Access:
  • Use IP restrictions and Virtual Network (VNet) integration to limit access to your functions.
  1. Set Up Alerts:
  • Configure alerts to notify you of unusual activity or potential security breaches.

Conclusion

Azure Functions offers a powerful and flexible platform for building serverless applications. By following best practices for security, you can ensure that your applications are robust and secure. With Azure Functions, you can focus on writing code and delivering value to your users without worrying about the underlying infrastructure.

Leave a Reply