Function set up
Last modified on Mon 07 Nov 2022

Project creation

Add a new project through the VS Function App template. This creates an azure function app that can contain multiple functions that share a common configuration such as environment variables, app settings, and host. All functions will be deployed together under the same function-app umbrella and scaled together.

Triggers

Different triggers can be used to trigger function execution. Here are some of the more popular ones:

[Function("FunctionName")]
public void Run([TimerTrigger("0 */5 * * * *")] MyInfo myTimer)
{
    _logger.LogInformation($"C# Timer trigger function executed at: {DateTime.Now}");
    _logger.LogInformation($"Next timer schedule at: {myTimer.ScheduleStatus.Next}");
    // your logic
}
[FunctionName("QueueTrigger")]
public static void Run(
    [QueueTrigger("myqueue-items", Connection = "StorageConnectionAppSetting")] string myQueueItem,
    ILogger log)
{
    // your logic
}

In cases where we need to use a different storage account than other functions in the library, you can use the StorageAccount attribute. That attribute specifies the name of the configuration value that contains the storage connection string:

[StorageAccount("ClassLevelStorageAppSetting")]
public static class AzureFunctions
{
    [FunctionName("QueueTrigger")]
    [StorageAccount("FunctionLevelStorageAppSetting")]
    public static void Run( //...
    {
    // your logic
    }
}
[Function("FunctionName")]
public HttpResponseData Run([HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequestData req)
{
    _logger.LogInformation("C# HTTP trigger function processed a request.");
    // your logic
    var response = req.CreateResponse(HttpStatusCode.OK);
    response.Headers.Add("Content-Type", "text/plain; charset=utf-8");
    response.WriteString("Welcome to Azure Functions!");
    return response;
}

Function app files

The default function app consists of:

Middleware

If you want to add middleware to Azure functions, all you have to do is create a new class that inherits from IFunctionsWorkerMiddleware and register it in your HostBuilder:

public class CustomMiddleware : IFunctionsWorkerMiddleware
{
    public async Task Invoke(FunctionContext context, FunctionExecutionDelegate next)
    {
        // code before exexecution
        await next(context);
        // code after execution
    }
}

Now register CustomMiddleware in the Program.cs class where you initialized your host builder:

var host = new HostBuilder()
    .ConfigureFunctionsWorkerDefaults(
        builder =>
        {
            builder.UseMiddleware<ExceptionLoggingMiddleware>();
        })
    .Build();

host.Run();

There is a limitation when using DI in this kind of middleware. You can use constructor injection just like in MVC middleware, but you can't use method injection because the Invoke method from the IFunctionsWorkerMiddleware interface accepts only two parameters.

To learn more about azure function middlewares, read here.

Best practices