To explain in detail how to reference a file in an Azure function some background information on the basics of Azure functions is necessary. To complete the story it will all be explained for C# script based function as well as C# compiled functions.
Azure functions can be built in the Azure portal, C# script based, or by using Visual Studio by using the Azure Function Tools for Visual Studio 2017 extension.
The Azure function tools provides a set of benefits:
- Functions can be edited, built and run from your local development computer
- Visual Studio can be used for development
- The Azure Functions project can be published directly to Azure
- Pre-compiled C# functions are deployed instead of C# script based functions which benefit from a performance perspective
Let’s take a look at some practical differences for both options.
Both are examples of a simple C# HttpTrigger.
[FunctionName("Function1")] public static async Task<HttpResponseMessage> Run([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]HttpRequestMessage req, TraceWriter log)
C# script function
public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, TraceWriter log)
It can be seen that the C# function uses attributes where the C# script function uses the settings which can be adjusted in the portal or can be maintained in a separate function.json file.
Project output structure
A C# function developed and compiled in Visual Studio and deployed to Azure has a slightly different output structure than a C# script function created in the Azure portal.
This is a copy of the directory below ‘\release(or debug)\net461’ on the local file system. As you can see there is a bin folder which contains the output assembly of the project as well as all the referenced assemblies. The function.json contains the bindings generated by the Azure Function tools from the C# code attributes defined.
Bindings are defined in function.json, where the actual C# script code is listed in run.csx, un-compiled and readable in the browser.
How to reference a file in the project within the function
How hard can it be, I hear you thinking… Yeah, my thoughts also..
What is the current working directory in the function code?
There are several options for getting a path in .NET
Assembly.GetExecutingAssembly().CodeBase – Gets the location of the assembly as specified originally; the place where the file is found.
Assembly.GetExecutingAssembly().Location – Gets the full path or UNC location of the loaded file that contains the manifest.
Environment.CurrentDirectory – Gets the current directory path of the project.
AppDomain.CurrentDomain.BaseDirectory – Gets the path of the entrypoint of the application or where the current AppDomain is created.
The output for the C# function, locally and published to Azure, as well as the output for the C# script function are displayed in the following figures.
In all three situations the different possibilities result in a different location returned and none of them are usable in all three situations.
For example the Codebase can be used when using a C# function, but when developing a C# script function this path is totally unusable.
To get information about the function or directory one has to dive into the Azure WebJobs SDK. After all Azure functions are based on WebJobs.
It seems that the method signature can take an additional parameter of type ExecutionContext.
Just add it and it’s ok, like this in a C# function:
public static async Task<HttpResponseMessage> Run([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]HttpRequestMessage req, TraceWriter log, ExecutionContext executionContext)
Or a C# script function:
public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, TraceWriter log, ExecutionContext executionContext)
So get the parent of this path to get the project directory.
And using an C# script function this results in ‘D:\home\site\wwwroot\HttpTriggerCSharp1’ which is the function directory over there.
When adding files and folders to the project in Visual Studio and deploy it to Azure, they are present in the structure:
Now the working directory is a known fact, referencing these files in the project is easy.
To get the project or function directory in an Azure function in Visual Studio or in the portal isn’t rocket science, but it took me some digging around in the SDK to get it.