Search code examples
.netmonowebassembly

How do I use Mono WebAssembly to run a simple .NET method in browser?


Let's say I have a .NET dll file on the server, that has this simple class:

public static class C {
    public static int Add(int a, int b) => a + b;
}

I want to invoke C.Add in browser using Mono's WebAssembly support.
(assume that I can download the dll into browser, e.g. with fetch)

Questions:

  1. What .js/.wasm files are required for Mono and where do I get those?
  2. Once everything is loaded, how do I actually invoke C.Add from JS?

I checked npm but I haven't found Mono WASM there.

Note: I already have a dll, so I'm interested in WASM IL interpreter and not WASM AOT build.


Solution

  • Here's what I found.

    Obtain Mono WASM

    Let's call the unpacked folder WASM-SDK.

    Note: you can skip following steps if you run packager.exe as described in Mono docs, but I want to describe the manual approach here for better understanding.

    Prepare .NET dlls

    Put the following dlls under your site root (lets say under managed folder):

    • Main dll that contains class C, let's call it app.dll
    • BCL dependencies, in this case you only need:
      1. WASM-SDK\wasm-bcl\wasm\mscorlib.dll
      2. WASM-SDK\wasm-bcl\wasm\Facades\netstandard.dll
      3. WASM-SDK\framework\WebAssembly.Bindings.dll

    Prepare Web files

    1. Copy mono.js and mono.wasm from WASM-SDK\release under your site root
    2. Register your Module and import mono.js:
    <script>
    window.Module = {};
    window.Module.onRuntimeInitialized = () => {
       const config = {
           vfsPrefix: "managed",
           deployPrefix: "managed",
           enableDebugging: 0
       };
       const assemblies = [
           'app.dll',
           'mscorlib.dll',
           'WebAssembly.Bindings.dll',
           'netstandard.dll'
       ];
       MONO.mono_load_runtime_and_bcl(
           config.vfsPrefix,
           config.deployPrefix,
           config.enableDebugging,
           assemblies,
           () => {
              Module.mono_bindings_init("[WebAssembly.Bindings]WebAssembly.Runtime");
              const add = Module.mono_bind_static_method("[app] C:Add");
    
              // ⬇️ This is what calls C.Add():
              console.log('C.Add:', add(1, 2));
           }
       )
    };
    <script>
    <script async src="mono.js"></script>
    
    1. If using IIS, make sure that there is a application/wasm mime type register for the .wasm extension.

    All done

    Now once you open your HTML you should see C.Add: 3 logged in the browser console.