Exploring Azure Functions: A Simple Scenario

Exploring Azure Functions: A Simple Scenario

Azure Functions is the primary tool for creating serverless solutions, and background jobs, shaping integration workflows, and building microservices in Azure. In this blog post, I'll demonstrate creating and deploying a simple Azure Function app.

This demo has two sections:

  1. The goal of the first section is to create a sample function app in the Azure portal and observe its request-response behavior.

  2. In the second section, I have a concrete scenario. According to the scenario, I need to regularly download and process a regulatory file from a government website. To do that, I'll create a function app that gets the source code of the government web page, extracts a particular URL from the page, and returns the URL in the function app HTTP Response body.

Section 1

  • In the Azure portal, search and navigate to the Function App page.

  • Click on the Create button and set the required values in the Basics form.

    1. Choose a unique name for your function app.

    2. Select .Net in the Runtime Stack list.

    3. Choose .Net 6 in the Version list as it's the latest LTS version of .NET at the time of this demo.

    4. Click the Review + Create button and finally click on Create. This will create your Function App resource.

    5. Click Go to Resource once your Function App is provisioned.

  • On the Overview page, click Create in Azure Portal button. This will promote a side window that allows you to create a function.

    1. Select the HTTP Trigger method in the function template list.

    2. You can change the function name as is. In this case, I'm leaving it as HttpTrigger1.

    3. Click Create.

  • Once the function is created, click on Code + Test. This will open a new page that shows your application files and a code editor. You'll see your function is created in run.csx file. This file contains a Run method as an entry point which accepts an HTTP Request and returns an HTTP Response. In order to test how it functions;

    1. Click Test/Run.

    2. In the opening panel, change the name value shown in the body section of the HTTP request.

    3. Click on Run.

  • See that the Run method returns the given name value in the HTTP response content.

  • As a second check, on the Code + Test page, click the Get function URL copy the function URL, and append the "&name=YourName" query string value to the URL. (Eq: *myapp.azureweb.com/?param1=value1&*name=Bilge)

  • Open the URL in a browser window and see that the name provided in the URL is returned in the response content as expected.

  • Before closing this section, on the Function App page, click Integration on the left menu. This will show you the diagram of the general flow of your Function App. I find this page very helpful in complex scenarios.

Section 2

  • In this section, as it's required to fetch the source code of a remote HTML web page and extract an element out of it, I'll need to use a specific HTML helper library. In this scenario, I'll move with the HtmlAgilityPack NuGet package which is categorized as an HTML parser tool. To install the NuGet package, I need to define the package as a dependency in a .proj file in the same location as the run.csx file. I'll explain how to do get to that point in the following steps.

  • In the Azure portal, navigate to the Function App page. In the left menu select Console.

  • In the console window, type "dir" command and list the directory content of the wwwroot folder. You'll see a folder with the same name as the Function App. I see "HttpTrigger1" in my case. Go inside the HttpTrigger1 folder by typing "cd YourFolderName" and list the directory content. You'll see that run.csx file is under that Function App folder.

  • So here, in this folder, we can create a "function.proj" file and define our NuGet package dependency inside it. Run "copy nul function.proj" to create an empty .proj file. We can now go to our Function App page and define project configuration in function.proj file.

  • In the Azure portal, from the left-hand navigation panel, navigate to your function and click Code + Test. In the dropdown list at the top of the code editor window, select "function.proj" file.

  • Copy this project configuration and paste it into the function.proj file. You can check and define the latest version of the pack in your demo. Click on Save.
<Project Sdk="Microsoft.NET.Sdk">
    <PropertyGroup>
        <TargetFramework>netstandard2.0</TargetFramework>
    </PropertyGroup>

    <ItemGroup>
        <PackageReference Include="HtmlAgilityPack" Version="1.11.54" />
    </ItemGroup>
</Project>
  • In the dropdown list select run.csx file.

  • Delete the code you see in run.csx file and paste the below code which reads a particular URL address from a remote web page. Click Save.

#r "Newtonsoft.Json"

using System.Net;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives;
using Newtonsoft.Json;
using HtmlAgilityPack; //reference to NuGet package containing HTML parser library
using System.Xml; //HtmlAgilityPack is dependent on this reference

public static async Task<IActionResult> Run(HttpRequest req, ILogger log)
{
//housekeeping log
    log.LogInformation("C# HTTP trigger function processed a request.");

//part of the original code. We keep it here just to continue demoing an input parameter
    string name = req.Query["name"];

//original code that responds to the HTTP call and pulls the name parameter from the request
    string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
    dynamic data = JsonConvert.DeserializeObject(requestBody);
    name = name ?? data?.name;

//code that expands the canned function with "real work" of parsing an HTML page
        var html = @"https://download.cms.gov/nppes/NPI_Files.html";
        HtmlWeb web = new HtmlWeb();
//dump the results of the web page call into an HTML (XML) document
        var htmlDoc = web.Load(html);
//parse the document to find the first instance of a bullet point with a link, by traversing the HTML to find the A tag under the LI tag.
        var monthlyLink = htmlDoc.DocumentNode
            .SelectSingleNode("//li/a")
            .Attributes["href"].Value;
//modified the original canned response with the value of the link parsed from the HTML
    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."
                : $"Monthly link: " + monthlyLink;
//original code that returns the response message
            return new OkObjectResult(responseMessage);
}
  • Click Test/Run and trigger a Run in the right test pane.

  • Once triggered, the Function App fetched the page content, filtered the necessary URL, and returned its value in the response content for us as shown in the image.