Routing In Azure Function

What is Routing ?

Routing is the process of directing an HTTP request to a controller which has the necessary business required to process the request and give an appropriate response. Using routing, we define the rules on the mapping between URLs to their respective controllers and actions. In the context of this article, It is the function route which can be used to send a http request to our Azure function.

Default function route in Azure functions

By default, the route for your azure function would be “localhost:7071/api/{functionName}”  

using System;  
using System.IO;  
using System.Threading.Tasks;  
using Microsoft.AspNetCore.Mvc;  
using Microsoft.Azure.WebJobs;  
using Microsoft.Azure.WebJobs.Extensions.Http;  
using Microsoft.AspNetCore.Http;  
using Microsoft.Extensions.Logging;  
using Newtonsoft.Json;  
  
namespace CustomRouting  
{  
    public static class Function1  
    {  
        [FunctionName("Function1")]  
        public static async Task<IActionResult> Run(  
            [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,  
            ILogger log)  
        {  
            log.LogInformation("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;  
  
            string responseMessage = string.IsNullOrEmpty(name)  
                ? "This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response."  
                : $"Hello, {name}. This HTTP triggered function executed successfully.";  
  
            return new OkObjectResult(responseMessage);  
        }  
    }  
}

In the above snippet, the function route is http://localhost:7071/api/Function1

Custom Routing using the Route Parameter by modifying the route parameter in the HttpTriggerAttribute

We can update or override the route for our Http Triggered Azure function by modifying the route parameter in the function1.cs. By default the route parameter is assigned as null.

Suppose we want the route to send a request to our Azure function as localhost:7071/api/hello then we would need to simply assign the route parameter as hello.

public static class Function1  
{  
    [FunctionName("Function1")]  
    public static async Task<IActionResult> Run(  
        [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = "Hello")] HttpRequest req,  
        ILogger log)  
    {  
        log.LogInformation("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;  

        string responseMessage = string.IsNullOrEmpty(name)  
            ? "This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response."  
            : $"Hello, {name}. This HTTP triggered function executed successfully.";  

        return new OkObjectResult(responseMessage);  
    }  
}

Now upon updating the route parameter, the new URL is http://localhost:7071/api/Hello

Passing value using function route in Azure function

We know that parameters or values can be passed with a url instead of using query string or request body in web applications and Web APIs. We often use this while we are sending a GET request to fetch data for a particular record.

Example - http://localhost:7071/api/Hello/1

To pass value in the function route in Azure function, we would have to modify the route parameter as “Hello/{valueName}”. Then add a parameter with the same name as the valueName in the Run method to use this value in your azure function. But adding {valueName} makes it a mandatory value to be passed.

public static class Function1  
{  
    [FunctionName("Function1")]  
    public static async Task<IActionResult> Run(  
        [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = "Hello/{id}")] HttpRequest req,  
        string id,  
        ILogger log)  
    {  
        log.LogInformation("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;  

        string responseMessage = string.IsNullOrEmpty(name)  
            ? "This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response."  
            : $"Hello, {name}. This HTTP triggered function executed successfully.";  

        return new OkObjectResult(responseMessage);  
    }  
}

Note

In case you don't pass a value in the function route, the request won't go to the Azure function. 

You can make it optional by adding a ? In the end of valueName like {valueName?}. Refer to the below snippet to make it optional in function route.

public static class Function1  
{  
    [FunctionName("Function1")]  
    public static async Task<IActionResult> Run(  
        [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = "Hello/{id?}")] HttpRequest req,  
        string id,  
        ILogger log)  
    {  
        log.LogInformation("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;  

        string responseMessage = string.IsNullOrEmpty(name)  
            ? "This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response."  
            : $"Hello, {name}. This HTTP triggered function executed successfully.";  

        return new OkObjectResult(responseMessage);  
    }  
}

Now upon updating the route parameter, the new URL can be http://localhost:7071/api/Hello/1 or http://localhost:7071/api/Hello or http://localhost:7071/api/Hello/ashirwad

Specifying the type of the valueName to be accepted in the function route.

By default, the type of valueName is string but you can also modify it to take value of a specific type by adding “:valueType” after the parameter name in the curly braces.

Example

To take an int type value in the function route you can specify the parameter as {valueName:int} and if you intend to make it optional then you can write it as {valueName:int?}.

You have to add a parameter in the run method with the same name and type as that of the valueName to use it in the business of your Azure function.

public static class Function1  
{  
    [FunctionName("Function1")]  
    public static async Task<IActionResult> Run(  
        [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = "Hello/{id:int?}")] HttpRequest req,  
        int id,  
        ILogger log)  
    {  
        log.LogInformation("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;  

        string responseMessage = string.IsNullOrEmpty(name)  
            ? "This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response."  
            : $"Hello, {name}. This HTTP triggered function executed successfully.";  

        return new OkObjectResult(responseMessage);  
    }  
}

Now upon updating the route parameter, the new URL can be http://localhost:7071/api/Hello/1 or http://localhost:7071/api/Hello 

Modifying the route prefix in Azure function

You must have noticed by now that almost all the function routes had /api/ in the route. In case, you wanted to change it, you can change it by modifying the content using the host.json.

Add the following snippet of line number 11 in the host.json to remove the route prefix in the function route.

{  
    "version": "2.0",  
  "logging": {  
    "applicationInsights": {  
      "samplingExcludedTypes": "Request",  
      "samplingSettings": {  
        "isEnabled": true  
      }  
    }  
  },  
  "extensions": {"http": {"routePrefix": ""}}  
}

Now upon updating the route parameter, the new URL can be http://localhost:7071/Hello/

In case you want to have a route prefix then you can add it inside the quotes of routePrefix in the above snippet. 

Conclusion

Routing is quite an essential part of developing an http based solution. Using the route, the request would map to the Azure function containing the business logic to perform the action for that particular request. It is quite flexible in Azure to configure a route as per your requirements. The above article discusses all the ways in which routing can be modified for an Azure function.