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.
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.
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
Console.WriteLine("Content-Type: text/plain"); Console.WriteLine(); Console.WriteLine("Hello, World");
To compile this, run the .NET 7 command line:
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
[[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
Here are some great resources: