String Literals in Azure Function Projects

Posted by

The New Project template for Azure Functions in Visual Studio 2019 takes care of most of the templating required to create your first functions. As your project grows to include more functions, an increasing number of string literals will find their way into the code base.

Be it in the FunctionName, input and output bindings, or configuration settings, these strings polute the code of a functions project.

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.");
                ...
		return name != null
			? (ActionResult)new OkObjectResult($"Hello, {name}")
			: new BadRequestObjectResult("Please pass a name on the query string or in the request body");
	}
}

Most of these literals aren’t going to change for the lifetime of the project. Even worse, some of these string literals get used in more than one place, making your code hard to maintain.

I’ve taken to organizing the literals into static classes that define a constant for each string literal. I’ve got a FunctionName class, a ConfigurationSetting class, and an HttpTriggerMethod class. For simplicity’s sake, I’ve put them all into a single file:

public static class FunctionName
{
	public const string Validator = "Validator";
	public const string Scheduler = "Scheduler";
}

public static class ConfigurationSetting
{
	public const string AzureWebJobsStorage = "AzureWebJobsStorage";
}

public static class HttpTriggerMethod
{
	public const string Get = "get";
	public const string Post = "post";
}

I then replace each occurence in the function trigger class by the appropriate constant.

[StorageAccount(ConfigurationSetting.AzureWebJobsStorage)]
public class Validator
{
	[return: Queue(BindingParameter.ValidationCompletedQueue)]
	[FunctionName(FunctionName.Validator)]
	public async Task<ValidationsComplete> Run([TimerTrigger(BindingParameter.ValidationTimer)]TimerInfo myTimer, ILogger log)
	{
		var flights = await _store.Get();

		if (flights.IsEmpty)
		{
			log.LogInformation($"No flights to validate.");
			return null;
		}

		var validFlights = new List<int>();
		var invalidFlights = new List<int>();

		foreach (var flight in flights)
		{
			...
    	}

		return new ValidationsComplete() { ValidFlightIds = validFlights, InvalidFlightIds = invalidFlights };
	}
}

I also created a BindingParameter class that declares constants for parameterized values. For example, BindingParameter.ValidationTimer’s constant value is “%TimerValue%”, where TimerValue is the name of a Configuration Setting in the Function app.

Moving string literals to constants improves readability. It also provides a single point of reference for values that are unlikely to change. It’s a low cost solution to a messy problem, and I’ve started using it in all my Function App projects.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s