When moving to Azure Functions or other FaaS offerings it’s possible to fall into the trap of “desktop development’ thinking, whereby a function is implemented as if it were a piece of desktop code. This may negate the benefits of Azure Functions and may even cause function failures because of timeouts. An Azure Function can execute for 5 minutes before being shut down by the runtime when running under a Consumption Plan. This limit can be configured to be longer in the host.json (currently to a mx of 10 minutes). You could also investigate something like Azure Batch.

Non Fan-Out Example

In this initial attempt, a blob-triggered function is created that receives a blob containing a data file. Each line has some processing performed on it (simulated in the following code) and then writes multiple output blobs, one for each processed line.

Uploading a normal sized input data file may not result in any errors, but if a larger file is attempted then you may get a function timeout:

Microsoft.Azure.WebJobs.Host: Timeout value of 00:05:00 was exceeded by function: Functions.ProcessBatchDataFile.

Fan-Out Example

Embracing Azure Functions more, the following pattern can be used, whereby there is no processing in the initial function. Instead the function just divides up each line of the file and puts it on a storage queue. Another function is triggered from these queue messages and does the actual processing. This means that as the number of messages in the queue grows, multiple instances of the queue-triggered function will be created to handle the load.

Suppose you are creating a library that has a central set of features and also additional features that are only available on some platforms. This means that when the project is built there are multiple assemblies created, one for each platform.

One way to achieve multi platform targeting is to create a number of separate projects, for example one for .NET Core , one for UWP, another one for .NET framework, etc. Then a shared source code project can be added and referenced by each of these individual projects; when each project is built separate binaries are produced. I’ve used this approach in the past, for example when working on FeatureToggle but is a little clunky and results in many projects in the solution.

Another approach is to have a single project that is not limited to a single platform output, but rather compiles to multiple platform assemblies.

For example, in Visual Studio 2017, create a new .NET Core class library project called TargetingExample and add a class called WhoAmI as follows:

Building now produces: "…\MultiTargeting\TargetingExample\TargetingExample\bin\Debug\netcoreapp1.1\TargetingExample.dll" and "…\MultiTargeting\TargetingExample\TargetingExample\bin\Debug\net461\TargetingExample.dll"”.

A new Windows Classic Desktop Console App project can now be added (and the .NET framework version changed to 4.6.1) and a reference to TargetingExample added.

The new console app contains the preceding code and when run produces the output: .NET Core.

Now we have a single project compiling for multiple target platforms. We can take things one step further by having different functionality depending on the target platform. One simple way to do this is to use conditional compiler directives as the following code shows:

Now when the project is built, the netcoreapp1.1\TargetingExample.dll will return “.NET Core” and net461\TargetingExample.dll will return “.NET Framework”. Each dll has been compiled with different functionality depending on the platform.

Update: The explicit <DefineConstants> for the different platforms are not required if you want to use the defaults, e.g. "NETCOREAPP1_1", "NET461", etc as per this Twitter thread and GitHub.

Running the application will result in an exception due to missing appSettings.config file: “System.IO.FileNotFoundException: 'The configuration file 'appSettings.json' was not found and is not optional.“ By default, FeatureToggle will expect toggles to be configured in this file, add an appSettings.json and set its Copy To Output Directory to “Copy if newer” and add the following content:

Using Feature Toggle in an ASP.NET Core App

Usage in an ASP.NET core app currently requires the configuration to be provided when instantiating a toggle, this may be cleaned up in future versions. For RC1 the following code shows the Startup class creating a FeatureToggle AppSettingsProviderand and passing it the IConfigurationRoot from the startup class.

Azure Functions allow small discrete pieces of code to execute in response to an external stimulus such as a HTTP request, message queue message, new blob data, etc. They can also be triggered manually from within the Azure Portal or set to execute on a specified schedule.

One of the interesting possibilities with the (currently in preview) Azure Function Proxies is the ability to create HTTP APIs that can be versioned and also deployed/managed independently.

For example, suppose there is a API that lives at the root “https://dctdemoapi.azurewebsites.net/api". We could have multiple resources under this root such as customer, products, etc.

So to get the product with an id of 42 we’d construct: “https://dctdemoapi.azurewebsites.net/api/products?id=42”.

If we wanted the ability to version the API we could construct “https://dctdemoapi.azurewebsites.net/api/v1/products?id=42” for version 1 and “https://dctdemoapi.azurewebsites.net/api/v2/products?id=42” for version 2, etc.

Using proxies we can use the format “https://dctdemoapi.azurewebsites.net/api/[VERSION]/[RESOURCE]?[PARAMS]”

Now we can create 2 proxies (for example in an Azure Function called “dctdemoapi”) that forwards the HTTP requests to other Function Apps (in this example dctdemoapiv1 and dctdemoapiv2).

Notice in the proxy config the use of the wildcard term “{*restOfPath}” – this will pass the remainder of the path segments to the backend URL, for example “products”, meaning a request to “https://dctdemoapi.azurewebsites.net/api/v1/products?id=42” will be sent to “https://dctdemoapiv1.azurewebsites.net/api/products?id=42”; and “https://dctdemoapi.azurewebsites.net/api/v2/products?id=42” will be sent to “https://dctdemoapiv2.azurewebsites.net/api/products?id=42”.

Now versions of the API can be updated/monitored/managed/etc independently because they are separate Function App instances, but code duplication is a potential problem; common business logic could however be compiled into an assembly and referenced in both Function Apps.

One of the NuGet packages I maintain is approaching 100,000 downloads. I thought it would be nice to get a notification on my phone when the number of downloads hit 100,000.

To implement this I installed the Flow app on my iPhone, wrote an Azure Function that executes on a timer, and calls into Flow.

Creating a Flow

The first step is to create a new Microsoft Flow that is triggered by a HTTP Post being sent to it.

The flow uses a Request trigger and a URL is auto generated by which the flow can be initiated.

The second step is the Notification action that results in a notification being raised in the Flow app for iOS.

Creating an Azure Function with Timer Trigger

Now that there is a URL to POST to to create notifications, a timer-triggered Azure Function can be created.

This function screen scrapes the NuGet page (I’m sure there’s a more elegant/less brittle way of doing this) and grabbing the HTML element containing the total downloads. If the total number of downloads >= 100,000 , then the flow URL will be called with a message in the body. The timer schedule runs once per day. I’ll have to manually disable the function once > 100,000 downloads are met.

In a previous article we saw how to get started with Azure Function Proxies. In addition to creating proxy URLs for HTTP functions in the same Function App, it is also possible to specifiy a backend URL that exists in a different Function App (or even a URL somewhere completely different). This essentially allows a single (HTTP) API for clients to use, that behind the scenes routes traffic to multiple Function Apps to enable the decomposing of a single large Function App into multiple smaller ones. This also enables isolation between different Function Apps for deployment, testing, management, monitoring, etc..

For example, suppose we have an HTTP function defined in a Function App called myazurecloudfunctions that GETs a customer using an id querystring parameter; a request for customer 42 would look like the following (with function authorization enabled):

Notice in this proxied URL the id 42 is specified in the URL, not as a querystring parameter. This is another feature of Azure Function Proxies that allows request parameters to be mapped from the proxy URL to the backend URL. In this example the proxy route template is “customer/{custId}” and the backend is set to “https://myazurecloudfunctions.azurewebsites.net/api/LoadCust?id={custId}” – notice the token {custId}.

With over 15 years experience, Jason Roberts is a former 5-time Microsoft .NET MVP, freelance developer, writer, and Pluralsight course author. He has written multiple books and is an open source contributor. In addition to enterprise software development, he has also designed and developed both Windows Phone and Windows Store apps.