Don't "admin" me!

This was somehow unexpected. I was flawlessly developing my API using Azure Functions and then BANG! - suddenly my functions are in error state. Just like that - no stack trace, no detailed explanation. I took me some time to realize, that they all have one thing in common - they share the admin part. Apparently Functions have some problems when you're using HttpTrigger with a custom route containg admin word. What is the reason?

Check the codebase

Let's take a quick look at the codebase of Functions. Finding a place, which causes the error is pretty simple:

internal static void ValidateHttpFunction(string functionName, HttpTriggerAttribute httpTrigger, bool isProxy = false)
	if (string.IsNullOrWhiteSpace(httpTrigger.Route) && !isProxy)
		// if no explicit route is provided, default to the function name
		httpTrigger.Route = functionName;

	// disallow custom routes in our own reserved route space
	string httpRoute = httpTrigger.Route.Trim('/').ToLowerInvariant();
	if (httpRoute.StartsWith("admin"))
		throw new InvalidOperationException("The specified route conflicts with one or more built in routes.");

As you can see, all routes which start with admin are disallowed. While this is perfectly fine, I couldn't find any mention in the documentation, which would clarify this. 

When in doubt always try to check the source. Some answers will be quite difficult to obtain, but you'll end up with a much better overall understanding of the library. The rest will be rather straightforward, nothing you can't handle, isn't it?

Tips & tricks - finding invocation identifier in Azure Function

It's Friday so it's time for something easy and simple yet useful. You may wondering what is an identifier you often see when running a function:

Well, it's not a function instance identifier since it changes each time a function runs. In fact it's an invocation identifier and, while it's not so obvious initially, you can easy inject it into your function.

To do so you need a class, which is called ExecutionContext. Normally it's not available by default, but by injecting it you'll gain some information about a job function invocation like:

  • invocation identifier
  • function name
  • function directory

Now when you prepare a function similar to mine:

public static void Run(
	[TimerTrigger("*/15 * * * * *")]TimerInfo timer,
	ExecutionContext context,
	TraceWriter log)
	log.Info($"Function called with `InvocationId` {context.InvocationId}");
	log.Info($"Function called with `FunctionName` {context.FunctionName}");
	log.Info($"Function called with `FunctionDirectory` {context.FunctionDirectory}");

You'll get following result: