C# (and .NET) in WebAssembly

The .NET (aka dotnet) ecosystem supports a variety of languages, including C# (C sharp) and ASP.NET. Programs that target .NET are compiled to an intermediary bytecode format that runs in the .NET Common Language Runtime (CLR). This makes .NET an example of a virtual machine language.

Available Implementations

The .NET ecosystem has long had support for browser-side WebAssembly via the Blazor toolkit.

The team at Microsoft is rapidly building out a number of WebAssembly tools. In 2022, it seems reasonable to expect that Microsoft will have new tooling for WebAssembly. C# compiled using the .NET toolchain will have access to these WebAssembly features.

At the time of this writing, the closest we have seen to a full WASI runtime is Steve Sanderson’s example .NET WASI Runtime.

In addition, browser-based support also seems to be available in the Elements compiler

Pros and Cons

Things we like:

  • Blazor is enjoying a surge of popularity in the browser
  • The .NET WASI Runtime looks excellent

For the most part, though, it is too early to speculate on the rest of the .NET tooling.

Example

Our example uses the .NET WASI Runtime. This is a preview and requires the supporting tools and build steps described in that repository.

All of our examples follow a documented pattern using common tools.

The example requires a project file ConsoleApp.csproj that imports the .NET WASI SDK:

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

    <!--
        As this is a preview, you will need to specify the path at which you
        checkout out the dotnet-wasi-runtime repo.
    -->
	<Import Project="path\to\Wasi.Sdk\build\Wasi.Sdk.props" />

	<PropertyGroup>
		<OutputType>Exe</OutputType>
		<TargetFramework>net7.0</TargetFramework>
		<ImplicitUsings>enable</ImplicitUsings>
		<Nullable>enable</Nullable>
	</PropertyGroup>

	<ItemGroup>
		<ProjectReference Include="path\to\src\Wasi.Sdk\Wasi.Sdk.csproj" ReferenceOutputAssembly="false" />
	</ItemGroup>

	<Import Project="path\to\Wasi.Sdk\build\Wasi.Sdk.targets" />

</Project>

Now we can write a simple C# program using WASI. Here is the text of Program.cs:

Console.WriteLine("Content-Type: text/plain");
Console.WriteLine();
Console.WriteLine("Hello, World");

To compile this, run the .NET 7 command line:

dotnet build

This produces a ConsoleApp.wasm file in the bin/Debug/net7.0 directory. We can execute that with Wasmtime:

$ wasmtime ./bin/Debug/net7.0/ConsoleApp.wasm
Content-Type: text/plain

Hello, World

To run this using Wagi, we need to create a simple modules.toml:

[[module]]
route = "/"
module = "bin/Debug/net7.0/ConsoleApp.wasm"

Then we can run Wagi:

$ wagi -c modules.toml

And using Curl or a web browser, we can hit http://localhost:3000 and see the output:

$ curl localhost:3000
Hello, World

Learn More

Here are some great resources: