I'm trying to create an Azure Function in F# that has an HTTP trigger and that retrieves data from Cosmos DB. The documentation only provides examples in C# for the CosmosDB binding and translating the code results in the error Cannot bind parameter 'toDoItems' to type IEnumerable`1
This C# example is able to log the id's of the items in Cosmos:
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Azure.WebJobs.Host;
using System.Collections.Generic;
using Microsoft.Extensions.Logging;
namespace Customer
{
public class ToDoItem
{
public string Id { get; set; }
public string PartitionKey { get; set; }
public string Description { get; set; }
}
public static class DocByIdFromQueryString
{
[FunctionName("Triggered")]
public static IActionResult Run(
[HttpTrigger(
AuthorizationLevel.Anonymous,
"get",
Route = null
)] HttpRequest req,
[CosmosDB(
databaseName: "customer-db",
collectionName: "todo-collection",
ConnectionStringSetting = "CosmosDBConnection",
SqlQuery = "select * from c"
)] IEnumerable<ToDoItem> toDoItems, ILogger log)
{
log.LogInformation("C# HTTP trigger function processed a request.");
foreach (ToDoItem toDoItem in toDoItems)
{
log.LogInformation(toDoItem.Id);
}
return new OkResult();
}
}
}
This is the F# translation from the working C# code. Both examples have the same dependency versions and use the same database (and connection string).
namespace Customer
open Microsoft.AspNetCore.Http
open Microsoft.AspNetCore.Mvc
open Microsoft.Azure.WebJobs
open Microsoft.Azure.WebJobs.Extensions.Http
open Microsoft.Extensions.Logging
module CosmosBindings =
type ToDoItem = {
Id : string
PartitionKey : string
Description : string
}
[<FunctionName("HttpTrigger")>]
let Run([<HttpTrigger(
AuthorizationLevel.Anonymous,
"get",
Route = null
)>] req: HttpRequest,
[<CosmosDB(
databaseName = "customer-db",
collectionName = "todo-collection",
ConnectionStringSetting = "CosmosDBConnection",
SqlQuery = "select * from c"
)>] toDoItems: ToDoItem seq) (log: ILogger) =
log.LogInformation "F# HTTP trigger function processed a request."
toDoItems
|> Seq.iter (fun item -> log.LogInformation item.Id)
OkObjectResult("Hello")
I've tried specifying bindings in an function.json file, but no matter what is added there the file in bin/HttpTrigger/function.json only contains the HttpTrigger (both C# and F#):
{
"generatedBy": "Microsoft.NET.Sdk.Functions-3.0.1",
"configurationSource": "attributes",
"bindings": [
{
"type": "httpTrigger",
"methods": [
"get"
],
"authLevel": "anonymous",
"name": "req"
}
],
"disabled": false,
"scriptFile": "../bin/Customer.dll",
"entryPoint": "Customer.CosmosBindings.Run"
}
The dependencies and function version are the same for both C# and F#:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
<AzureFunctionsVersion>v3</AzureFunctionsVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Azure.WebJobs.Extensions.CosmosDB" Version="3.0.3" />
<PackageReference Include="Microsoft.NET.Sdk.Functions" Version="3.0.1" />
</ItemGroup>
<ItemGroup>
<Compile Include="GetCustomer.fs" />
</ItemGroup>
<ItemGroup>
<None Update="host.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="local.settings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<CopyToPublishDirectory>Never</CopyToPublishDirectory>
</None>
</ItemGroup>
</Project>
The errors from running the F# example:
[2/19/2020 4:01:52 PM] Starting JobHost
[2/19/2020 4:01:52 PM] Starting Host (HostId=havardandaestensenvippsnosmacboo, InstanceId=faf11b1c-b81d-49d2-8876-e4ef8785dc9f, Version=3.0.13107, ProcessId=30665, AppDomainId=1, InDebugMode=False, InDiagnosticMode=False, FunctionsExtensionVersion=(null))
[2/19/2020 4:01:52 PM] Loading functions metadata
[2/19/2020 4:01:52 PM] 1 functions loaded
[2/19/2020 4:01:52 PM] Generating 1 job function(s)
[2/19/2020 4:01:52 PM] Microsoft.Azure.WebJobs.Host: Error indexing method 'HttpTrigger'. Microsoft.Azure.WebJobs.Host: Cannot bind parameter 'toDoItems' to type IEnumerable`1. Make sure the parameter Type is supported by the binding. If you're using binding extensions (e.g. Azure Storage, ServiceBus, Timers, etc.) make sure you've called the registration method for the extension(s) in your startup code (e.g. builder.AddAzureStorage(), builder.AddServiceBus(), builder.AddTimers(), etc.).
[2/19/2020 4:01:52 PM] Error indexing method 'HttpTrigger'
[2/19/2020 4:01:52 PM] Microsoft.Azure.WebJobs.Host: Error indexing method 'HttpTrigger'. Microsoft.Azure.WebJobs.Host: Cannot bind parameter 'toDoItems' to type IEnumerable`1. Make sure the parameter Type is supported by the binding. If you're using binding extensions (e.g. Azure Storage, ServiceBus, Timers, etc.) make sure you've called the registration method for the extension(s) in your startup code (e.g. builder.AddAzureStorage(), builder.AddServiceBus(), builder.AddTimers(), etc.).
[2/19/2020 4:01:52 PM] Function 'HttpTrigger' failed indexing and will be disabled.
[2/19/2020 4:01:52 PM] No job functions found. Try making your job classes and methods public. If you're using binding extensions (e.g. Azure Storage, ServiceBus, Timers, etc.) make sure you've called the registration method for the extension(s) in your startup code (e.g. builder.AddAzureStorage(), builder.AddServiceBus(), builder.AddTimers(), etc.).
[2/19/2020 4:01:52 PM] Initializing function HTTP routes
[2/19/2020 4:01:52 PM] Mapped function route 'api/HttpTrigger' [get] to 'HttpTrigger'
[2/19/2020 4:01:52 PM]
[2/19/2020 4:01:52 PM] Host initialized (199ms)
[2/19/2020 4:01:52 PM] Host started (206ms)
[2/19/2020 4:01:52 PM] Job host started
[2/19/2020 4:01:52 PM] The 'HttpTrigger' function is in error: Microsoft.Azure.WebJobs.Host: Error indexing method 'HttpTrigger'. Microsoft.Azure.WebJobs.Host: Cannot bind parameter 'toDoItems' to type IEnumerable`1. Make sure the parameter Type is supported by the binding. If you're using binding extensions (e.g. Azure Storage, ServiceBus, Timers, etc.) make sure you've called the registration method for the extension(s) in your startup code (e.g. builder.AddAzureStorage(), builder.AddServiceBus(), builder.AddTimers(), etc.).
Removing the type from the F# code and just returning toDoItems from CosmosDB also results in an error.
[2/19/2020 4:22:33 PM] Generating 1 job function(s)
[2/19/2020 4:22:33 PM] No job functions found. Try making your job classes and methods public. If you're using binding extensions (e.g. Azure Storage, ServiceBus, Timers, etc.) make sure you've called the registration method for the extension(s) in your startup code (e.g. builder.AddAzureStorage(), builder.AddServiceBus(), builder.AddTimers(), etc.).
[2/19/2020 4:22:33 PM] Initializing function HTTP routes