Welcome to todays post.
Today I will be discussing and showing how to create an Azure Serverless Function.
I will also be showing how to add Function security to the serverless function.
The implementation will initially be within a local development environment, which will allow you to develop and test the function and ensure it can run before migrating it to Azure. I will explain migration to Azure in the next post.
Also, before you can develop and test the Azure functions locally, you should install and enable the Azure Storage Emulator, which is allows your locally hosted Azure functions to access storage. More details on how to obtain and setup are here.
Creating a serverless Azure function can be done using two different publishing tools:
- Visual Studio Code
- Visual Studio
I will show how to create and publish an Azure function using Visual Studio.
To start off, create a new project.
Select the Azure Function template.

In the next screen, select HttpTrigger:

Browse the storage account:

Select the Azure storage account:

Next, select the Function access rights:

Note that even if you selected the Anonymous security option in order to test in the local environment, once you deploy your serverless function to Azure, the authentication will be enforced.
After the project is created, the following skeleton code is generated:
using System.IO;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Azure.WebJobs.Host;
using Newtonsoft.Json;
namespace BookLoanOverdueFunctionApp
{
public static class Function1
{
[FunctionName("Function1")]
public static IActionResult Run([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]HttpRequest req, TraceWriter log)
{
log.Info("C# HTTP trigger function processed a request.");
string name = req.Query["name"];
string requestBody = new StreamReader(req.Body).ReadToEnd();
dynamic data = JsonConvert.DeserializeObject(requestBody);
name = name ?? data?.name;
return name != null
? (ActionResult)new OkObjectResult($"Hello, {name}")
: new BadRequestObjectResult("Please pass a name on the query string or in the request body");
}
}
}
By default, the route to call the function is of the form:
http://<app name >.azurewebsites.net/api/<function name>
If we wish to add extra routing or a parameter to allow more complexity on the function, we can use routing. This is done by creating a route within the binding for the http trigger definition:
using System.IO;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Azure.WebJobs.Host;
using Newtonsoft.Json;
namespace BookLoanOverdueFunctionApp
{
public static class OverdueBookFunction
{
[FunctionName("OverdueBookFunction")]
public static IActionResult Run(
[HttpTrigger(
AuthorizationLevel.Function, "get", "post",
Route = "Loan/{id?}")]HttpRequest req,
int? id,
TraceWriter log)
{
log.Info("C# HTTP trigger function processed a request.");
int? loanId = id ?? 0;
return id != null
? (ActionResult)new OkObjectResult($"The Loan {id} is overdue. Processing notice for borrower.")
: new BadRequestObjectResult("Please pass in a valid Loan ID.");
}
}
}
For the above function, after applying this route, the new route will be:
http://<app_name>.azurewebsites.net/api/Loan/{id}
For this routing to take effect, the project must be built and the updated function.json that holds the updated trigger binding will be generated in the bin\Debug\netstandard2.0\[function]\ folder.
Then function.json will then be updated with the following binding configuration:
{
"generatedBy": "Microsoft.NET.Sdk.Functions-1.0.13",
"configurationSource": "attributes",
"bindings": [
{
"type": "httpTrigger",
"route": "Loan/{id?}",
"methods": [
"get",
"post"
],
"authLevel": "function",
"name": "req"
}
],
"disabled": false,
"scriptFile": "../bin/BookLoanOverdueFunctionApp.dll",
"entryPoint": "BookLoanOverdueFunctionApp.OverdueBookFunction.Run"
}
If the routing is not correctly defined and is null in the Run() parameter list and an attempt is made to use the routing during an call to the azure function, then the following error will display:
[7/01/2020 4:32:15 AM] The following 1 functions are in error:
[7/01/2020 4:32:15 AM] Run: Microsoft.Azure.WebJobs.Host: Error indexing method 'OverdueBookFunction.Run'. Microsoft.Azure.WebJobs.Host: Cannot bind parameter 'id' to type Nullable`1. Make sure the parameter Type is supported by the binding. If you're using binding extensions (e.g. ServiceBus, Timers, etc.) make sure you've called the registration method for the extension(s) in your startup code (e.g. config.UseServiceBus(), config.UseTimers(), etc.).
If the routing parametrization is invalid, such as being defined as “id: int?” instead of “id?” then the following error will display by the host during runtime:
[7/01/2020 6:57:31 AM] A ScriptHost error has occurred
[7/01/2020 6:57:31 AM] Microsoft.AspNetCore.Routing: An error occurred while creating the route with name 'OverdueBookFunction' and template 'api/Loan/{ id: int?}'. Microsoft.AspNetCore.Routing: The constraint entry ' id' - ' int' on the route 'api/Loan/{ id: int?}' could not be resolved by the constraint resolver of type 'DefaultInlineConstraintResolver'.
[7/01/2020 6:57:31 AM] Stopping Host
The function server local host will run under a console as shown:

The function host will listen to the port showing.
To test the function, copy the URL in green:

Paste the URL into a browser with the {id} string replaced with an integer.
After submitting, you will hit the breakpoint as shown in VS 2017 IDE:

After continuing, the following will be output to the console:

Now check the browser and the response output will show:

It’s working!
We have a working Azure serverless function.
Our next goal will be to deploy this to Azure. I will show this in the next post.

Andrew Halil is a blogger, author and software developer with expertise of many areas in the information technology industry including full-stack web and native cloud based development, test driven development and Devops.