Azure Functions - Web API - Part 1
Implementing an Azure Function is the theme here, specifically creating a highly elastic web API quickly. But, what does highly elastic
really mean? Initially, when this API is deployed to production there will be 0 users of it. Not so great, but this is what happens when something brand new is deployed. During this time of little usage, the cost for the API will be nominal, if not completely free. As the use of the API increases, then increases some more, then increases even more. Azure Functions will grow with the demand. Recall in the first post, Azure Functions are event-driven. So, they only react to events being raised. The more events raised, the more resources required. Depending on the selected plan, this service can scale one function to have up to 200 instances. How about some quick back of the napkin math here, with the resourcefully scaled out.
- Average request length: .02 sec
- Number of requests/instance/second: 50 requests
- Number of requests/second for the service: 10,000 requests
10,000 requests a second is quite a bit of traffic for one endpoint.
Just how easy can this be?
EASY, I promise. Here is one implementation in 10 lines of class implementation:
using System;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
namespace WebApi.Functions
{
public static class DateTimeFunction
{
[FunctionName("datetime")]
public static IActionResult GetDateTime(
[HttpTrigger(AuthorizationLevel.Function, "get", "post", "put", "patch", "delete")] HttpRequest req,
ILogger log)
{
return new OkObjectResult(new { CurrentDateTime = DateTime.Now });
}
}
}
Let's start with the class definition, nothing amazing going on here. If you have ever created a CommandLine project in C#.NET this will look familiar. There is a public static class named DateTimeFunction. The static part is a little bit interesting, I suppose. With Azure Functions the implementation can be static. If there is no need to have a constructor, the best option is to make the function static. The function will then be a singleton, meaning for every execution of the function the same instance will be used. There is no need for the .NET runtime to create a new instance for execution. The runtime already has it loaded and is ready to use it.
What about the next line, the attribute on top of the method definition? The [FunctionName("{name}")]
attribute comes from the Microsoft.Azure.WebJobs
namespace. Meaning it is directly from the Microsoft Azure team. As you may have already guessed, this is used for defining the name of the function. Once deployed to an Azure environment, in Azure's portal for this resource you will be able to see a list of functions that are deployed in the environment. As well as, the execution metrics for each of the functions. Again, as you may have already guessed this name must be unique per definition.
The definition of the method is not all that interesting. Except IActionResult
. If you have ever implemented a more traditional web API using the MVC namespace, this should look familiar. As all the API responses implement IActionResult
, allowing the development team to use the appropriate responses for the endpoint and return something more defined than object
.
Next, let's take a look at the first parameter. It starts with an attribute of HttpTrigger
, there are a couple of arguments. The first is the authorization required to trigger the function. The second is a list of HTTP methods the function will respond to. As you can see in the example above, this function will be triggered by the most common HTTP methods. The type of the parameter is an HttpRequest. Where all the context of the API call is passed into the function for use.
The second parameter is the same for all of the functions I have ever written and seen. The parameter is of type ILogger
this allows the implementer to easily write data to the logs. As one might assume, this can be used for informational and debugging purposes.
Lastly, the body of the function. While this particular function is not all that valuable, it is generally easy to comprehend for all skill levels. The response is a new anonymous object, containing one property CurrentDateTime
. The value of the property is the current server time the function is executing on. If we were to deploy this to an Azure Functions resource, the time would always return the current UTC. This anonymous object is wrapped in another object of type OkObjectResult
this will result in a 204 response code to the caller. There are several of these response types available for us implementers. The list is quite large, so rather than enumerate them in this post, here is the Microsoft documentation for the possibilities.
Now you know how to create a basic Azure Function web API endpoint. There is more to cover on this topic alone. Such as, now that we know how to make one. How do we go about implementing a replacement for a C.R.U.D controller we already have in production? Stay tuned for the next post on creating a more advanced Azure Function web API solution.
P.S. Everything you saw in this post and more can be found on my GitHub, including a PostMan collection for all the API endpoints in the project.