I have spent a day on this and I really thought this would be something trivial.
There are about a dozen options surrounding the HTTP binding "Route" parameter, the related "Run" method signature, and the underlying web API routing mechanism documentation. I've tried each of the, and each one seems to throw a different error. By the way, this trial and error was particularly frustrating and time consuming.
Azure Function Bindings
https://docs.microsoft.com/en-us/azure/azure-functions/functions-bindings-http-webhook
ASP.NET Route Constraints Docs
Functions bindings allow you to define the "Route" string in each function config file which defines the entry point for that function. It effectively works the same way a the "Route" Annotations worked from ASP.NET (which is new to me). Thus, the Azure Function docs link to the Constraints docs for advanced usage.
Our use case is not advanced, we want our function work something like the following:
Handle something like the following route:
"route" : "/books/{bookName}"
Which maps to a function with a Run() signature that looks something like:
Run(HttpRequestMessage req, string bookName, TraceWriter log)
If there's no bookName, our function will return the array of all books. If there's a bookname, it will return the details of that book. Standard API stuff.
According to the "constraints" doc, we must make an adjustment for the bookName to make it an optional URI parameter, and we have a few options. Here are the two examples/options provided:
public class BooksController : ApiController
{
[Route("api/books/locale/{lcid:int?}")]
public IEnumerable<Book> GetBooksByLocale(int lcid = 1033) { ... }
}
public class BooksController : ApiController
{
[Route("api/books/locale/{lcid:int=1033}")]
public IEnumerable<Book> GetBooksByLocale(int lcid) { ... }
}
Currently, neither of the two options above work in functions. The bindings don't allow the equal sign in the function.json, and any optional parameters in the Run() method would need to be the "last" parameters, and we don't have control over the order of the Run() parameters. Even if we could change them, we wouldn't want to, as having TraceWriter log be the last parameter is a sensible convention we'd like to follow.
Now, the Azure Functions docs provides an optional parameter example that seems to be very straightforward, but somehow manages to dodge the specific use case above.
Here is the route from function.json:
"route": "products/{category:alpha}/{id:int?}"
Here is the method signature:
Run(HttpRequestMessage request, string category, int? id, TraceWriter log)
So, the difference here is that the parameter they marked as optional is specifically an int, which is a nullable type. The azure function runtime clearly passes through a null int if the URL doesn't contain it, thereby bypassing the requirement of making "id" an optional parameter to the method.
If you try the same trick with a string parameter, you get this:
error CS0453: The type 'string' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'Nullable'
Is there a reasonable solution to achieve an optional string parameter in Azure Functions?
If so, please provide a tip on the tutorial. If not, please clearly indicate this limitation on the tutorial.
ApiController
samples. Shorter question would be easier for future readers. - Mikhail Shilkov