Azure Function Filters

This feature would solve the problem of customizing or request pipeline and help common logic to share across Azure functions. If you are a .NET developer, you would have implemented ASP.NET MVC filters in your web application. The Function Filters are way similar to ASP.NET filters.

In the following, let us see the various filter types available in Functions and how to implement it in a sample HTTP trigger Function.
Below are the two filters which are available for Functions;

  1. FunctionInvocationFilterAttribute
  2. FunctionExceptionFilterAttribute

FunctionInvocationFilterAttribute

This filter can be executed before and after reprocessing logic in the particular function.

FunctionExceptionFilterAttribute

This Filter will be executed if there is an exception thrown by the Azure Function.

The above mentioned two filter can be applied globally to all functions, it can applied either to a class level or Function level respectively.

Now, let us implement the two filters in a HTTP trigger Function. For this purpose, create a new Function in Visual Studio with HTTP trigger. Then, make necessary changes to the template code as below or you may just copy paste it.

// Modified Template Code
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Azure.WebJobs.Host;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System;
using System.Diagnostics;
using System.IO;
using System.Threading;
using System.Threading.Tasks;

namespace FunctionFilters
{
    public class Function1:IFunctionExceptionFilter, IFunctionInvocationFilter
    {
        [FunctionName("Function1")]
        public  async Task<IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
            ILogger log)
        {

            Debug.WriteLine("C# HTTP trigger function processed a request.");

            string name = req.Query["name"];

            string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
            dynamic data = JsonConvert.DeserializeObject(requestBody);
            name = name ?? data?.name;

            return name != null
                ? (ActionResult)new OkObjectResult($"Hello, {name}")
                : new BadRequestObjectResult("Please pass a name on the query string or in the request body");
        }

        public Task OnExceptionAsync(FunctionExceptionContext exceptionContext, CancellationToken cancellationToken)
        {
            Debug.WriteLine($"Exception raised by the application {exceptionContext.Exception.ToString()}");
            return Task.CompletedTask;
        }

        public Task OnExecutedAsync(FunctionExecutedContext executedContext, CancellationToken cancellationToken)
        {
            Debug.WriteLine($"This part should be executed at last");
            return Task.CompletedTask;
        }

        public Task OnExecutingAsync(FunctionExecutingContext executingContext, CancellationToken cancellationToken)
        {
            Debug.WriteLine($”This part should be executed at before function code");
            return Task.CompletedTask;
        }
    }
}

The template code has got the following modifications (just to know):

  1. The function class must be changed from static to instance
  2. You should implement function filters at class level and override the respective method OnExceptionAsync, OnExecutedAsync and OnExecutingAsync.

Once, the changes to the code is done. Run it locally, may be in your favourite IDE to test how it works. Happy Learning!!

Share this on...

Rate this Post:

Share:

Topics:

Azure

Tags: