How to use the HTTP Trigger in Azure Functions v4 C# .NET 6

I recently got stuck in a project involving a few simple HTTP endpoints running on Azure Functions version 4. In fact, in recent years the .NET Core specifications for web are in continuous evolution and all the good tutorials out there on .NET Core 3.1 Functions can no longer be applied on the most recent version of the functions.

In this tutorial I want to show how to do the most common functionality you need when designing a new endpoint, like extracting data from a query parameter, path parameter, body and how to handle optional params.

Reading Path Parameters

Path parameters (or route parameters) are those that are passed as part of the url, like

https://example.com/api/elements/1

This is a common pattern used to access a specific resource based on its ID for example, and has been almost untouched since the .NET Framework.

Assuming we want to read the number 1 in the example above, we can use the following function definition:

public HttpResponseData Run([HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "elements/{elementId}")] HttpRequestData req, int elementId)
        {
            // function implementation here
        }

This is straightforward, you just add the Route argument to HttpTrigger and enter the name of the variable you want to capture between curly braces, and then add an extra typed argument to the function with the same name you used in the route to capture it (in this case we expect an integer so declared as an int).

I’ll add some more examples below:

// using 2 different path parameters
        public HttpResponseData Run([HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "elements/{elementId}/{someOtherId}")] HttpRequestData req, int elementId, string someOtherId)
        {
            // function implementation here
        }

        // the path parameter doesn't have to be at the end of the route
        public HttpResponseData Run([HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "elements/{elementId}/details")] HttpRequestData req, int elementId)
        {
            // function implementation here
        }

Advanced

Looking at the official docs, one thing worth mentioning is that the Route argument doesn’t need to be specified and is null by default. The function name will be used to name the endpoint, and the path parameters will be inferred from the arguments you add in the function method signature.

In the docs you will find other advanced information, like additional information you can add in the route placeholder. For instance

Route = "elements/{elementId:int}/{someOtherId:alpha?}

defines the type of the parameter, and more importantly, it allows you to have an optional path parameter, which would otherwise not be possible.

Reading Query Parameters

Query parameters are appended to the url after the ? character, for example

https://example.com/api/elements?color=red&size=500

This is used when

  • Doing a search
  • Selecting a set of entities based on some attributes
  • Generally all the data retrieval that doesn’t involve fetching by ID

This is in continuous evolution, and I had to spend some time to find what I was looking for. The easiest way to read query params is the following

public HttpResponseData Run([HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "elements")] HttpRequestData req)
        {
            var queryParameters = HttpUtility.ParseQueryString(req.Url.Query);
            var colorQueryParam = queryParameters.Get("color");
            var sizeQueryParam = queryParameters.Get("size");

            // function implementation here
        }

It’s important to note that colorQueryParam and sizeQueryParam are both nullable strings. This means that you need to add your own logic to ensure that the mandatory query parameters are there and are of the correct type.

I made an example below

if (colorQueryParam == null)
            {
                return req.CreateResponse(HttpStatusCode.BadRequest);
            }

            int sizeQueryParamInt;
            if (sizeQueryParam == null || !int.TryParse(sizeQueryParam, out sizeQueryParamInt))
            {
                return req.CreateResponse(HttpStatusCode.BadRequest);
            }

This unfortunately is a pretty big letdown for whom, like me, was used to .NET Framework WebAPI2, which automatically matched the right handler based on the query parameters, and did an automatic type check.

Leave a Reply