DEV Community

Cover image for How to Create Custom Middleware in Azure Functions: A Step-by-Step Guide with .NET 8
CodeStreet
CodeStreet

Posted on

How to Create Custom Middleware in Azure Functions: A Step-by-Step Guide with .NET 8

This blog post will walk us through creating custom middleware in Azure Functions using .NET 8. We’ll build a custom exception handler middleware that catches unhandled exceptions, logs them, and returns a standardized error response.

By the end of this guide, you'll clearly understand how to create and use middleware in your Azure Functions projects.

Azure Functions has become a go-to solution for building serverless applications. One of the powerful features of Azure Functions in .NET 8 is the ability to use middleware in isolated process mode.

Middleware allows you to inject logic into the request-processing pipeline, making it an essential tool for handling cross-cutting concerns like logging, authentication, and error handling.

What is Middleware?

Middleware is a component that processes incoming requests before they reach your core application logic. Think of it as a filter or gatekeeper that can modify requests, enforce security policies, or handle errors.

In the context of Azure Functions, middleware can be used to perform tasks like logging, validation, and exception handling across multiple functions without repeating code.

Step 1: Setting Up Your Azure Functions Project

Before we dive into the middleware, let’s set up a basic Azure Functions project in .NET 8.

Step 1: Setting Up Your Azure Functions Project

Create a New Project:

  • Open Visual Studio 2022 and create a new Azure Functions project.
  • Choose the “ .NET 8 Isolated Process ” template.
  • Name your project and click “ Create.”

Install Required Packages:

Ensure that you have the necessary NuGet packages installed for Azure Functions and middleware. The Microsoft.Azure.Functions.Worker package should already be included in your project.

Step 2: Creating Custom Exception Handling Middleware

Now that your project is set up, let’s create a custom middleware class that will handle exceptions globally.

using Microsoft.Azure.Functions.Worker;
using System.Text.Json;

public class CustomExceptionHandler : IFunctionsWorkerMiddleware
{
    public async Task Invoke(FunctionContext context, FunctionExecutionDelegate next)
    {
        try
        {
            await next(context);
            Console.WriteLine("No exception occurred");
        }
        catch (Exception ex)
        {
            var request = await context.GetHttpRequestDataAsync();
            var response = request!.CreateResponse();
            response.StatusCode = System.Net.HttpStatusCode.InternalServerError;

            var errorMessage = new { Message = "An unhandled exception occurred. Please try again later", Exception = ex.Message };
            string responseBody = JsonSerializer.Serialize(errorMessage);

            await response.WriteStringAsync(responseBody);

            Console.WriteLine("Exception occurred");
            context.GetInvocationResult().Value = response;
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Explanation:

  • Try-Catch Block: The Invoke method wraps the next middleware or function execution in a try-catch block. If an exception occurs, it is caught and handled.
  • Custom Error Response: When an exception is caught, the middleware creates an HTTP response with a 500 status code. It also serializes a custom error message, which includes a generic message and the exception details.
  • Logging: The middleware logs whether an exception occurred or not, making it easier to track issues during development.

Step 3: Registering the Middleware in the Function App

With the middleware created, the next step is to register it in your Azure Functions app.

using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.Hosting;

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

host.Run();
Enter fullscreen mode Exit fullscreen mode

Explanation:

  • UseMiddleware: The UseMiddleware method registers your custom middleware in the function app’s pipeline. This ensures that the middleware is invoked for every incoming request, before any function logic is executed.

Step 4: Modify/Create Azure Function to Test the Middleware

Let’s create a simple Azure Function that will deliberately cause an exception, allowing us to test our middleware.

using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.Functions.Worker.Http;

[Function("Custom-Middleware")]
public IActionResult Run([HttpTrigger(AuthorizationLevel.Anonymous, "get")] HttpRequest req)
{
    _logger.LogInformation("C# HTTP trigger function processed a request.");

    int.TryParse(req.Query["number"], out int number);
    int res = 10 / number; // This will throw a DivideByZeroException if 'number' is 0

    return new OkObjectResult(new { result = res });
}
Enter fullscreen mode Exit fullscreen mode

Explanation:

  • DivideByZeroException: This function parses a number from the query string and divides 10 by that number. If the number is 0, a DivideByZeroException will be thrown, which our middleware will catch and handle.

Step 5: Running and Testing the Function

Now that everything is set up, let’s run the function app and test it by triggering the function with different inputs.

  • Valid Input: If you pass a non-zero number, the function will return the result of the division.
  • Invalid Input (Zero): If you pass 0, the function will throw an exception. The middleware will catch this exception, log it, and return a standardized error message to the client.

Here’s what the error response might look like:

{
    "Message": "An unhandled exception occurred. Please try again later",
    "Exception": "Attempted to divide by zero."
}
Enter fullscreen mode Exit fullscreen mode

Conclusion

In this post, we’ve explored how to create and use custom middleware in Azure Functions using .NET 8 in isolated process mode. We walked through a practical example of an exception-handling middleware that catches unhandled exceptions and returns a standardized error response.

If you found this guide helpful, consider sharing it with others and stay tuned for more Azure Functions tutorials!

Top comments (0)