MissingMethodException with Suave & Fable.Remoting

165 Views Asked by At

Here is a minimal sample that will reproduce the issue.

Trying to hit that endpoint, either with a Fable client or just navigating to http://127.0.0.1:8080/ITestAPI/Test causes the server to throw a Method not found:

[ERR] request failed
System.MissingMethodException: Method not found: 'Microsoft.FSharp.Collections.FSharpMap`2<System.String,System.Object> HttpContext.get_userState()'.
   at [email protected](Unit unitVar)
   at Microsoft.FSharp.Control.AsyncPrimitives.CallThenInvoke[T,TResult](AsyncActivation`1 ctxt, TResult result1, FSharpFunc`2 part2) in F:\workspace\_work\1\s\src\fsharp\FSharp.Core\async.fs:line 386
   at [email protected](AsyncActivation`1 ctxt)
   at [email protected](AsyncActivation`1 ctxt) in F:\workspace\_work\1\s\src\fsharp\FSharp.Core\async.fs:line 577
   at [email protected](AsyncActivation`1 ctxt) in C:\Users\username\code\test\suavetest\Program.fs:line 12
   at [email protected](AsyncActivation`1 ctxt) in F:\workspace\_work\1\s\src\fsharp\FSharp.Core\async.fs:line 577
   at Microsoft.FSharp.Control.Trampoline.Execute(FSharpFunc`2 firstAction) in F:\workspace\_work\1\s\src\fsharp\FSharp.Core\async.fs:line 105

I've hit my head against this for a couple of days now, with no progress. Same error occurs using both .Net Core 3.1 and .Net 5.

Anyone have any insight into what might be causing this? I'm not seeing any open issues with Fable.Remoting or Suave about this, so I have to imagine it's something I'm doing wrong?

2

There are 2 best solutions below

1
On BEST ANSWER

This looks like an FSharp.Core mismatch issue. Are you depending on a specific FSharp.Core package that is less than 4.7.2?

In general, unless you are writing a library intended for distribution on NuGet, you should not pin your dependency on FSharp.Core at all. For applications, always use whatever the .NET SDK provides and you'll virtually never run into these issues.

Explicitly FSharp.Core package references are an additional issue for library authors who need to worry about which F# versions their package is compatible with. If that is not a requirement for you, then it's best to never opt into that additional bit of complexity.

Using your sample code in a brand-new .NET 5 console app works for me:

Test.fsproj

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net5.0</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <Compile Include="Program.fs" />
  </ItemGroup>

  <ItemGroup>
    <PackageReference Include="fable.remoting.suave" Version="4.13.0" />
  </ItemGroup>

</Project>

Program.fs

open System
open Suave
open Fable.Remoting.Server
open Fable.Remoting.Suave

type ITestAPI = {
    Test : Async<string>
}

let greetFun = 
    async {
        return "It works!"
    }

let testAPI = {
    Test = greetFun
}

let webApp  = 
    Remoting.createApi()
    |>Remoting.fromValue testAPI
    |> Remoting.withDiagnosticsLogger (printfn "%s")
    |>Remoting.buildWebPart

[<EntryPoint>]
let main argv =
    startWebServer defaultConfig webApp
    0 // return an integer exit code

Under the covers, this uses the FSharp.Core in the SDK that is version 4.7.0 or higher, which makes it compatible with the library you're using and results in no exception at runtime.

0
On

I ran into the same issue. Phillip is correct, but is missing an important piece. The problem is that the current version of Fable.Remoting.Suave is built against Suave 2.5.6. If you reference this specific version of Suave, you can have both dependencies in your .fsproj file:

  <ItemGroup>
    <PackageReference Include="Fable.Remoting.Suave" Version="4.29.0" />
    <PackageReference Include="Suave" Version="2.5.6" />
  </ItemGroup>