Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 207
Andrey Shchekin Avatar asked Feb 06 '19 00:02

Andrey Shchekin


1 Answers

Here's what I found.

Obtain Mono WASM

  • The steps are described here: docs/getting-started/obtain-wasm-sdk.md
  • Short summary: you have to download and unpack a build from Jenkins

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.

like image 184
Andrey Shchekin Avatar answered Oct 05 '22 06:10

Andrey Shchekin