Saturday, March 24, 2018

Azure function apps: creating a shared .csx file that uses an external library


In this post we are going to discuss how to make multiple C# Azure functions use a shared .csx that uses an external library.

The problem

Imagine the situation is like this, you have two functions in your function app that each take a blob as an input and output a bunch images with different sizes. These functions would have different inputs and outputs, say that take their input from different queues and output the images in some blob storage path.

The resizing library of choice is ImageResizer, which is available on NuGet. To install it, we add a project.json file in the root of our function with content like this.

{
  "frameworks": {
    "net46": {
      "dependencies": {
        "ImageResizer": "4.0.5"
      }
    }
  }
}

This automatically installs and adds a reference to ImageResizer to our function so we can start resizing the images.

So these two functions are essentially the same, they take an input image and output a bunch of resized images, so it's sane that we extract the common piece of code (the resizing part) into its own module.

The catch here is that the common code have to use the ImageResizer library, and the only way to install and manage it automatically is to use the project.json file.

The Solution

Some initial steps are required to make this work, so here are the prerequisites.

First thing is to add the shared file to your function app so that both of your functions can reference it.

  • go to https://portal.azure.com/ and login to your account.
  • Open Function Apps, choose your function app then click the Platform Features tab from the top navigation bar.
  • From the DEVELOPMENT TOOLS section choose Advanced tools (Kudu).
  • From the top menu, Debug console -> CMD.
  • navigate from the file explorer, choose site -> wwwroot. This is where all your functions live.

Now in the console

> mkdir shared
> cd shared
> touch resize.csx

This creates a file called resize.csx inside the shared folder and that's the file we will be using for our image resizing logic.

Now, the solutions.

One possible solution would be to downlad the .dll file for the library and upload it to the shared folder then import it inside the resize.csx file. You wouldn't then need the project.json file. This would work but you will be losing the advantage of package management that NuGet gives you, so I can't recommend this approach.

A better solution is to take advantage of the fact that the loaded .csx files are much like importing header files in the C language, in which they become part of your file and get access to all available namespaces.

We will start from the docs, which mentions that you import a shared library with the #load directive.

So in the run.csx file of one of the functions, import the shared file. Assuming that it has a function called resize that takes an image as a Stream and an array of sizes to output, it would look like this.

#load "../shared/resize.csx"

public static void Run(Stream someImage) {
    resize(someImage, sizesArray);
}

So this way the shared resize function is available in our function app and the ImageResizer is available to the resize function, due to the fact that they share the same context.

Then for any other functions that need to use the resize function, add the project.json file with the ImageResizer package and you're good to go.


That's it. These are the simplest solutions to deal with that situation. Sure there are other solutions out there, so if you have some solution that you would recommend please share it with us.