I set out to learn about Azure Functions and this is the knowledge I have gathered so far.

To have something to work with, I decided to migrate the ASP.NET Core Web API for “My latest online activities” to Azure Functions.

As background, refer to these related blog posts:

To get some basic understanding, read the introduction over at Microsoft Docs:

You can create your functions in the browser on the Azure Portal, but I find it to be a bit cumbersome. My approach is to use the Azure Functions CLI tool to scaffold a project, put it on GitHub and deploy to Azure Functions with continuous deployment.

Azure Functions CLI

Command line tool for Azure Function

The Azure Functions CLI provides a local development experience for creating, developing, testing, running, and debugging Azure Functions.

Read the docs at:

Install:

npm i -g azure-functions-cli

npm i -g azure-functions-cli

Install globally

Create Function App:

func init

func init

Create a new Function App in the current folder. Initializes git repo.

Create Function:

func function create

func function create

Create a new Function from a template, using the Yeoman generator

Run:

func host start

func host start

Launches the functions runtime host

So that is what I did when I created the latest-functions project. I’ll come back to that later. First let’s talk about my CommandQuery package.

CommandQuery

Command Query Separation (CQS) for ASP.NET Core and Azure Functions

Remember the background:

To migrate the ASP.NET Core Web API project to a Azure Functions app, I first needed to extend the CommandQuery solution.

As a result I ended up with three packages on NuGet:

  • CommandQuery
    • Common base functionality
  • CommandQuery.AspNetCore
    • Command Query Separation for ASP.NET Core
  • CommandQuery.AzureFunctions
    • Command Query Separation for Azure Functions

In this blog post I will cover the CommandQuery.AzureFunctions package:

Provides generic function support for commands and queries with HTTPTriggers

To get more information about the project, read the documentation over at the GitHub repository.

Get started:

Sample code:

When I was writing the code specific to Azure Functions, I needed to add dependencies. It makes sense to depend on the same assembly versions as the Azure Functions hosting environment use. Therefore, I ended up creating a project to gather that information.

AzureFunctionsInfo

⚡️ Information gathered on Azure Functions by executing Azure Functions ⚡️

I basically wanted to get information about available Assemblies and Types in the Azure Functions hosting environment.

The code and all the information gathered can be viewed at:

For example, this is some important information I found out:

The type TraceWriter comes from:

{
  "Type": "Microsoft.Azure.WebJobs.Host.TraceWriter",
  "Assembly": "Microsoft.Azure.WebJobs.Host, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
}

latest-functions

Okay, so now it is time to cover the actual Azure Functions app I created. The code was migrated from an existing ASP.NET Core Web API project.

Remember the background:

The app has one query function to get data on my latest:

  • Blog post
  • GitHub repo and commit
  • Instagram photo

The source code is available at:

The project was created with the Azure Functions CLI tool:

After the scaffolding, the generated code needed to be modified.

This is the end result:

function.json

Defines the function bindings and other configuration settings

  • authLevel set to anonymous
    • No API key is required
  • route query/{queryName} added
  • method post added
    • Array of the HTTP methods to which the function will respond

project.json

To use NuGet packages in a C# function, upload a project.json file to the function’s folder in the function app’s file system.

  • Only the .NET Framework 4.6 is supported, specify net46
  • CommandQuery.AzureFunctions, version 0.2.0
    • This will make the use of queries and query handlers possible in the function

bin folder

If you need to reference a private assembly, you can upload the assembly file into a bin folder relative to your function and reference it by using the file name (e.g. #r "MyAssembly.dll").

bin

  • The queries and query handlers used in this function are located in Latest.dll
  • Code: Latest

Make sure that private assemblies are built with <TargetFramework>net46</TargetFramework>.

run.csx

This is the code for the actual function. Written in scriptcs, you can enjoy a relaxed C# scripting syntax.

  • The #r "Latest.dll" directive reference the query assembly from the bin folder
  • Import the namespaces System.Reflection and CommandQuery.AzureFunctions
  • Create a static instance of QueryFunction and inject a QueryProcessor with the query Assembly. This will make IoC container find the correct query handlers for the queries.
  • Add the string queryName argument to the function signature so the corresponding route will work
  • Let the QueryFunction handle the query and return the result

When the code is done, only four things remains to get it running in the cloud:

  1. Push to GitHub, Bitbucket or Visual Studio Team Services
  2. Log in to the Azure portal
  3. Create a function app
  4. Set up continuous deployment

The end result of all this can be viewed at:

The code for the SPA that uses the function:

Testing

While building your functions, you want to test early and often.

Run the functions locally with the command:

func host start

If you need to specific CORS origins use something like:

func host start --cors http://localhost:3000

When the functions are running locally you can manually test them with tools like Postman or curl.

Advice from Microsoft:

Postman

Postman

The Postman collection for this function:

curl

Commands for this function hitting the cloud endpoints:

curl -X POST http://latest-functions.azurewebsites.net/api/query/BlogQuery -H "content-type: application/json" -d "{}"

curl -X POST http://latest-functions.azurewebsites.net/api/query/GitHubQuery -H "content-type: application/json" -d "{'Username': 'hlaueriksson'}"

curl -X POST http://latest-functions.azurewebsites.net/api/query/InstagramQuery -H "content-type: application/json" -d "{}"

Resources

Other people are testing the functions with code:

If you are using CommandQuery together with Azure Functions you can unit test your command and query handlers.

For example like this:

(Yeah, I know! Not really unit testing, but you get the point)