Introduction

I’m familiar with the common default templates from dotnet new in .NET 5.0 as they’ve been consistent for the past few releases so as I’ve started my journey with Azure Functions I thought “what would an Azure Function version of the default WebApi template look like?”.

So let’s take a look!

Overview

Before we start to implement the Azure Function what does the default WebApi template do? It starts off with a api controller with a single Get action.

[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
    private static readonly string[] Summaries = new[]
    {
        "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
    };

    private readonly ILogger<WeatherForecastController> _logger;

    public WeatherForecastController(ILogger<WeatherForecastController> logger)
    {
        _logger = logger;
    }

    [HttpGet]
    public IEnumerable<WeatherForecast> Get()
    {
        var rng = new Random();
        return Enumerable.Range(1, 5).Select(index => new WeatherForecast
        {
            Date = DateTime.Now.AddDays(index),
            TemperatureC = rng.Next(-20, 55),
            Summary = Summaries[rng.Next(Summaries.Length)]
        })
        .ToArray();
    }
}

It takes an ILogger instance from the constructor injection and all the work is done in the Get action. We have a Summaries lookup array which is used by the Random number generation to create random temperatures in a range. This is then used to look up the associated weather summary string to present back to the call of the api.

Function Implementation

After creating an Azure Function and converting it into being the same functionality as our webapi controller end point there were actually less differences than I was expecting.

Let’s take a look at the end Azure Function and see what differences were required.

public class WeatherForecastFunction
{
    private static readonly string[] Summaries = new[]
    {
        "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
    };

    private readonly ILogger<WeatherForecastFunction> _logger;

    public WeatherForecastFunction(ILogger<WeatherForecastFunction> logger)
    {
        _logger = logger;
    }

    [FunctionName("WeatherForecast")]
    public async Task<IActionResult> Get(
        [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = null)] HttpRequest req)
    {
        _logger.LogInformation("About to generate weather forecast data ...");

        var rng = new Random();
        var data = Enumerable.Range(1, 5).Select(index => new WeatherForecast
        {
            Date = DateTime.Now.AddDays(index),
            TemperatureC = rng.Next(-20, 55),
            Summary = Summaries[rng.Next(Summaries.Length)]
        })
        .ToArray();

        return new OkObjectResult(data);
    }
}

As we can see the Summaries lookup string array was exactly the same. The ILogger<WeatherForecastFunction> dependency through constructor injection was the same. More information can be found on my previous post about logging in Azure Functions.

The biggest difference is the change from a Controller Action to a “Function” which has a HttpTrigger. The HttpTrigger tells the Azure Function that a Http “GET” Request will be the trigger, or initiator, of this function. This can be initiated through a browser request, a REST client or even something like curl. Anything which can initiate a Http Request can call it. Due to the AuthorizationLevel it is open to anyone to call and there are no specific routing attributes applied either.

That’s it. That’s all the changes between webapi and Azure Function.

On starting of the Function we are presented with the end point to perform a “GET” on to execute the call.

Functions:

        WeatherForecast: [GET] http://localhost:7071/api/WeatherForecast

Conclusion

In this post we have seen what it takes to implement the default WeatherForecastController as an Azure Function. I under took this experiment to start to learn more about Azure Functions and to be honest I was expecting more work to be done to achieve the same data being returned.

So what does this give us? Well it essentially comes down to hosting. A WebApi is an “Application” and has to be hosted as such. This can be on an Azure App Service, Docker container or even in IIS on a Virtual Machine. An Azure Function is more of a “ServerLess” methodology. This aids with different ways of billing in Azure and allows the developers to think about the server less.

The more I look into Azure Functions the more interesting they become. If you have any cool stories or interesting pointers please let me know on Twitter @WestDiscGolf