Element.Azure.Functions.Worker.Extensions.RoutePriority 1.1.0

dotnet add package Element.Azure.Functions.Worker.Extensions.RoutePriority --version 1.1.0
                    
NuGet\Install-Package Element.Azure.Functions.Worker.Extensions.RoutePriority -Version 1.1.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Element.Azure.Functions.Worker.Extensions.RoutePriority" Version="1.1.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Element.Azure.Functions.Worker.Extensions.RoutePriority" Version="1.1.0" />
                    
Directory.Packages.props
<PackageReference Include="Element.Azure.Functions.Worker.Extensions.RoutePriority" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Element.Azure.Functions.Worker.Extensions.RoutePriority --version 1.1.0
                    
#r "nuget: Element.Azure.Functions.Worker.Extensions.RoutePriority, 1.1.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Element.Azure.Functions.Worker.Extensions.RoutePriority@1.1.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Element.Azure.Functions.Worker.Extensions.RoutePriority&version=1.1.0
                    
Install as a Cake Addin
#tool nuget:?package=Element.Azure.Functions.Worker.Extensions.RoutePriority&version=1.1.0
                    
Install as a Cake Tool

HTTP route resolution priority for Isolated Azure Functions

Provides correct and deterministic HTTP route resolution priority for Azure Functions running in Isolated mode.

Potentially ambiguous routes like these will resolve properly when called with a url that could match either one.

/api/{userId}
/api/ping

Usage

Add the Element.Azure.Functions.Worker.Extensions.RoutePriority Nuget package to your Isolated Azure Functions project.

NOTE: Due to how the Azure Functions metadata generator works, you must actually use the extension in a function declaration. To meet that requirement, you must add the [RoutePriority] input binding attribute to any one of your HttpTrigger functions (does not need to be all of them):

[Function("Ping")]
public HttpResponseData Ping([HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "ping")] HttpRequestData req, [RoutePriority] object ignore)
{
    // ... your code ...
}

How does it work?

See my original blog post for full details of the problem and how the extension works internally. In the in-process model, the solution from that blog post works great.

However, in the the isolated functions model, the functions host and your functions code run as two separate processes. The functions host recieves the incoming request then communicates with your worker process via gRPC. But the only way to get access to the IWebJobsRouter is to do it from the host.

Unfortunately, the code you write in your function app only runs in the worker process and there is no way to 'reach into' the host to modify its behavior.

Except, there is. And it is via Binding Extensions.

Binding extensions are ways to add your own custom trigger types, input bindings, and output bindings. In order to allow them to work, they also have to run in the host. So this solution creates a custom extension that allows code (in this case, code to reorder the route priority order) to run on the host.

One limitation of extensions is that they are only geared towards bindings. As such, your function app code must make use of at least one binding from your extension or else the function extension metadata generator will strip out the extension information from the generated host code. That is why the [RoutePriority] input binding attribute needs to be applied somewhere in a function in your function app - it doesnt do anything, other than prevent the rest of the extension code from being complied out.

The actual mechanisms of how extensions work is:

  • you add a reference to a worker extension library (in this case: Element.Azure.Functions.Worker.Extensions.RoutePriority available via Nuget)
  • that worker extension library has an [ExtensionInformation] attribute that points to a different Nuget package that contains the actual logic which will be injected into the host (in this case: Element.Azure.WebJobs.Extensions.RoutePriority, which is also available on Nuget but should not be referenced directly from your function app)
  • when you compile your function app, the function metadata generator scans your code for binding extensions, creates a temporary .csproj file, and outputs the necessary .dlls and and emits an extensions.json file with metadata about your extension and the entry points

You don't need to know any of that in order to take advantage of this package, but it might be interesting to know what is going on under the hood.

References

Credit goes to Maarten Balliauw for documenting how to write custom extensions for isolated functions. It was invaluable in understanding how things worked internally.

The source code for the functions metadata generator (where you can see how items are stripped out if not used) is also interesting reading.

The source code for the Microsoft-provided extensions was also a great reference, as was the Dapr extension source code.

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.1.0 171 2/24/2025
1.0.2 7,275 12/5/2023
1.0.1 181 12/4/2023
1.0.0 209 10/13/2023