FSharp.Data missing method exception

308 views Asked by At

I am trying to resolve a MissingMethodException in a pre-compiled F# Azure Function. The exception is thrown when I call an extension method from FSharp.Data.CssSelectorExtensions.

The function is defined in a .Net Framework 4.6.2 class library. I am using the current versions of FSharp.Core (4.2.3) and FSharp.Data (2.3.3). (I have tried older versions of both but the problem persists.) I have added a binding redirect for FSharp.Core per the standard guidance for this kind of problem. The code compiles cleanly but fails when it is executed. It also fails if I attempt to invoke the extension method directly as a simple static method.

Any guidance on how I can get rid of this exception would be much appreciated!

Function Code

module httpfunc

open System.Net
open System.Net.Http
open Microsoft.Azure.WebJobs.Host
open FSharp.Data
open FSharp.Data.CssSelectorExtensions

let Run(req: HttpRequestMessage, log: TraceWriter) =
    async {
        let doc = HtmlDocument.Load("https://google.com")
        let node = doc.CssSelect("div.ctr-p") // <-- method is missing
        return req.CreateResponse(HttpStatusCode.OK)
    } |> Async.RunSynchronously

Exception Message

 mscorlib: Exception while executing function: Functions.httpfunc. 
 mscorlib: Exception has been thrown by the target of an invocation. 
 fsfuncs: Method not found: 'Microsoft.FSharp.Collections.FSharpList`1<FSharp.Data.HtmlNode> CssSelectorExtensions.CssSelect(FSharp.Data.HtmlDocument, System.String)'.

app.config

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2" />
  </startup>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="FSharp.Core" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-4.4.1.0" newVersion="4.4.1.0" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
</configuration>

packages.config

<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="FSharp.Core" version="4.2.3" targetFramework="net462" />
  <package id="FSharp.Data" version="2.3.3" targetFramework="net462" />
  ...
</packages>

.fsproj

<Project ToolsVersion="15.0" ... />
  <PropertyGroup>
    <RootNamespace>fsfuncs</RootNamespace>
    <AssemblyName>fsfuncs</AssemblyName>
    <TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
    <TargetFSharpCoreVersion>4.4.1.0</TargetFSharpCoreVersion>
    <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
    <Name>fsfuncs</Name>
  </PropertyGroup>
  ...
</Project>

Edit

On Fyodor Soikin's advice I've determined that multiple versions of FSharp.Core.dll are being loaded: one from the GAC and one from the NuGet packages folder.

Two versions of FSharp.Core.dll are loaded.

1

There are 1 answers

1
Tomas Petricek On BEST ANSWER

The execution engine behind Azure Functions already loads FSharp.Core.dll (because it depends on F# compiler services to run your F# scripts) and I think you will always get the version of FSharp.Core.dll that is specified by the execution engine's app.config, which is 4.4.0.0.

I might be missing something, but I think your best chance is to make your function use version 4.4.0.0. Could you try removing the explicit FSharp.Core reference? That way, the runtime should load just the (already pre-loaded) version of FSharp.Core.