MissingMethodException 与 Suave & Fable.Remoting

MissingMethodException with Suave & Fable.Remoting

Here 是将重现该问题的最小示例。

尝试访问该端点,无论是使用 Fable 客户端还是导航至 http://127.0.0.1:8080/ITestAPI/Test 都会导致服务器抛出找不到方法:

[ERR] request failed
System.MissingMethodException: Method not found: 'Microsoft.FSharp.Collections.FSharpMap`2<System.String,System.Object> HttpContext.get_userState()'.
   at Fable.Remoting.Suave.SuaveUtil.setBinaryResponseBody@26-1.Invoke(Unit unitVar)
   at Microsoft.FSharp.Control.AsyncPrimitives.CallThenInvoke[T,TResult](AsyncActivation`1 ctxt, TResult result1, FSharpFunc`2 part2) in F:\workspace\_work\s\src\fsharp\FSharp.Core\async.fs:line 386
   at Fable.Remoting.Server.Proxy.makeEndpointProxy@80-10.Invoke(AsyncActivation`1 ctxt)
   at Microsoft.FSharp.Control.AsyncPrimitives.unitAsync@577.Invoke(AsyncActivation`1 ctxt) in F:\workspace\_work\s\src\fsharp\FSharp.Core\async.fs:line 577
   at Program.greetFun@12-1.Invoke(AsyncActivation`1 ctxt) in C:\Users\username\code\test\suavetest\Program.fs:line 12
   at Microsoft.FSharp.Control.AsyncPrimitives.unitAsync@577.Invoke(AsyncActivation`1 ctxt) in F:\workspace\_work\s\src\fsharp\FSharp.Core\async.fs:line 577
   at Microsoft.FSharp.Control.Trampoline.Execute(FSharpFunc`2 firstAction) in F:\workspace\_work\s\src\fsharp\FSharp.Core\async.fs:line 105

我已经为此苦苦思索了几天,没有任何进展。使用 .Net Core 3.1 和 .Net 5 时出现同样的错误。

任何人都知道可能导致这种情况的原因吗?我没有看到 Fable.Remoting 或 Suave 有任何未解决的问题,所以我不得不想象这是我做错了什么?

这看起来像是 FSharp.Core 不匹配问题。您是否依赖于低于 4.7.2 的特定 FSharp.Core 软件包?

一般来说,除非您正在编写一个旨在在 NuGet 上分发的库,否则您应该而不是 将您的依赖固定在 FSharp.Core 上。对于应用程序,请始终使用 .NET SDK 提供的任何内容,您几乎永远不会 运行 遇到这些问题。

明确地 FSharp.Core 包引用对于库作者来说是一个额外的问题,他们需要担心他们的包与哪些 F# 版本兼容。如果这不是您的要求,那么最好永远不要选择额外的复杂性。

在全新的 .NET 5 控制台应用程序中使用您的示例代码适合我:

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

在幕后,这使用了 SDK 中的 FSharp.Core 版本 4.7.0 或更高版本 ,这使其与您正在使用的库兼容并在 运行 时间没有异常。

我运行遇到了同样的问题。菲利普是正确的,但遗漏了一个重要的部分。问题是 Fable.Remoting.Suave 的当前版本是针对 Suave 2.5.6 构建的。如果您引用这个特定版本的 Suave,您可以在 .fsproj 文件中同时拥有这两个依赖项:

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