F# for Azure function v4 with Net6

Hi all

I would like to create an azure function with f# and dependency injection. Which shouldn’t be too hard and it works all fine when I am running it locally in the debugger but once I am uploading it to Azure and try to test it it cannot find the microsoft.extension.abstraction libray or in other cases throws this System.Private.CoreLib: Value cannot be null. (Parameter ‘g’).

Does anyone have a working configuration for F# and net6 with function version v4 and injection?
I have kind of this setup. This doesnt look so bad.

Might be possible that I have to use older version of some libraries but i cannot seem to find any hints.

fsproj

<PropertyGroup>
    <TargetFramework>net6.0</TargetFramework>
    <AzureFunctionsVersion>v4</AzureFunctionsVersion>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="FSharp.Data" Version="4.2.8" />
    <PackageReference Include="Microsoft.Azure.Functions.Extensions" Version="1.1.0" />
    <PackageReference Include="Microsoft.Extensions.Configuration" Version="6.0.1" />
    <PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="6.0.1" />
    <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="6.0.0" />
    <PackageReference Include="Microsoft.NET.Sdk.Functions" Version="4.1.1" />
    <PackageReference Update="FSharp.Core" Version="6.0.4" />
  </ItemGroup>

startup.fs

type MyStartup() =
    inherit FunctionsStartup()

    override u.Configure(builder: IFunctionsHostBuilder) =
        
        let cfg =
            ConfigurationBuilder()
                .AddUserSecrets("secretfile")
                .AddEnvironmentVariables()
                .Build()

        let config = getConfiguration(cfg.GetSection("setting"))
        
        builder.Services.AddSingleton<Configuration>(config) |> ignore

[<assembly: FunctionsStartup(typeof<MyStartup>)>]
do()

#function file

type HttpTrigger(config:Configuration) =
        
    [<FunctionName("Function1")>]
    member x.Run ([<HttpTrigger(AuthorizationLevel.Function, "get", Route = null)>]req: HttpRequest) (log: ILogger) =
        task {
            
            return OkObjectResult(tags) :> IActionResult
        } 

I have an F# Azure function for function v4 and .net 6, but I’m not using DI, and I’m using paket instead of nuget, so my setup might not be super helpful for you. My fsproj has

<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net6.0</TargetFramework>
    <AzureFunctionsVersion>v4</AzureFunctionsVersion>
  </PropertyGroup>
  <ItemGroup>
    <Compile Include="MyFile.fs" />
  </ItemGroup>
  <ItemGroup>
    <None Update="host.json">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </None>
    <None Update="local.settings.json">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      <CopyToPublishDirectory>Never</CopyToPublishDirectory>
    </None>
  </ItemGroup>
  <Import Project="..\.paket\Paket.Restore.targets" />
</Project>

and my paket.dependencies is

nuget FSharp.Core

nuget SafetyFirst
nuget SafetyFirst.Strict

nuget Microsoft.NET.Sdk.Functions 4.0.1
nuget Microsoft.Extensions.DependencyInjection 6.0
nuget Microsoft.Extensions.DependencyInjection.Abstractions 6.0
nuget Microsoft.Extensions.Logging.Abstractions 6.0

(hmmm, I see DI dependencies in there, but we’re just running code directly from a trigger function like this

  [<FunctionName("MyFunc")>]
  let myFunc([<TimerTrigger("0 0 17 1 * *")>] myTimer: TimerInfo, log: ILogger) =
    ...

and not doing the whole Startup file with an overridden Configure member or anything like that)

1 Like

Thanks for your reply.
At least somebody who can make it work. :joy:

I need the connection to usersecrets for local debugging and to azure key vault for the secrets. And di is quite useful for that. I think that is exactly where it goes wrong. without that it works also for me.

I am also trying the isolated approach now. Let’s see how this goes. appreciate if anyone has a working example of dotnet-isolated and DI for net6.

1 Like