Scott Hanselman

What is Blazor and what is Razor Components?

March 19, '19 Comments [12] Posted in ASP.NET | Javascript | Open Source
Sponsored By

I've blogged a little about Blazor, showing examples like Compiling C# to WASM with Mono and Blazor then Debugging .NET Source with Remote Debugging in Chrome DevTools as well as very early on asking questions like .NET and WebAssembly - Is this the future of the front-end?

Let's back up and level-set.

What is Blazor?

Blazor is a single-page app framework for building interactive client-side Web apps with .NET. Blazor uses open web standards without plugins or code transpilation. Blazor works in all modern web browsers, including mobile browsers.

You write C# in case of JavaScript, and you can use most of the .NET ecosystem of open source libraries. For the most part, if it's .NET Standard, it'll run in the browser. (Of course if you called a Windows API or a Linux specific API and it didn't exist in the client-side browser S world, it's not gonna work, but you get the idea).

The .NET code runs inside the context of WebAssembly. You're running "a .NET" inside your browser on the client-side with no plugins, no Silverlight, Java, Flash, just open web standards.

WebAssembly is a compact bytecode format optimized for fast download and maximum execution speed.

Here's a great diagram from the Blazor docs.

Blazor runs inside your browser, no plugins needed

Here's where it could get a little confusing. Blazor is the client-side hosting model for Razor Components. I can write Razor Components. I can host them on the server or host them on the client with Blazor.

You may have written Razor in the past in .cshtml files, or more recently in .razor files. You can create and share components using Razor - which is a mix of standard C# and standard HTML, and you can host these Razor Components on either the client or the server.

In this diagram from the docs you can see that the Razor Components are running on the Server and SignalR (over Web Sockets, etc) is remoting them and updating the DOM on the client. This doesn't require Web Assembly on the client, the .NET code runs in the .NET Core CLR (Common Language Runtime) and has full compatibility - you can do anything you'd like as you are not longer limited by the browser's sandbox.

Here's Razor Components running on the server

Per the docs:

Razor Components decouples component rendering logic from how UI updates are applied. ASP.NET Core Razor Components in .NET Core 3.0 adds support for hosting Razor Components on the server in an ASP.NET Core app. UI updates are handled over a SignalR connection.

Here's the canonical "click a button update some HTML" example.

@page "/counter"

<h1>Counter</h1>

<p>Current count: @currentCount</p>

<button class="btn btn-primary" onclick="@IncrementCount">Click me</button>

@functions {
int currentCount = 0;

void IncrementCount()
{
currentCount++;
}
}

You can see this running entirely in the browser, with the C# .NET code running on the client side. .NET DLLs (assemblies) are downloaded and executed by the CLR that's been compiled into WASM and running entirely in the context of the browser.

Note also that I'm stopped at a BREAKPOINT in C# code, except the code is running in the browser and mapped back into JS/WASM world.

Debugging Razor Components on the Client Side

But if I host my app on the server as hosted Razor Components, the C# code runs entirely on the Server-side and the client-side DOM is updated over a SignalR link. Here I've clicked the button on the client side and hit the breakpoint on the server-side in Visual Studio. No there's no POST and no POST-back. This isn't WebForms - It's Razor Components. It's a SPA app written in C#, not JavaScript, and I can change the locations of the running logic, while the UI remains always standard HTML and CSS.

Debugging Razor Components on the Server Side

It's a pretty exciting time on the open web. There's a lot of great work happening in this space and I'm very interesting to see how frameworks like Razor Components/Blazor and Phoenix LiveView change (or don't) how we write apps for the web.


Sponsor: Manage GitHub Pull Requests right from the IDE with the latest JetBrains Rider. An integrated performance profiler on Windows comes to the rescue as well.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

Updating jQuery-based Lazy Image Loading to IntersectionObserver

April 11, '18 Comments [4] Posted in ASP.NET | HTML5 | Javascript
Sponsored By

The Hanselminutes Tech PodcastFive years ago I implemented "lazy loading" of the 600+ images on my podcast's archives page (I don't like paging, as a rule) over here https://www.hanselminutes.com/episodes. I did it with jQuery and a jQuery Plugin. It was kind of messy and gross from a purist's perspective, but it totally worked and has easily saved me (and you) hundreds of dollars in bandwidth over the years. The page is like 9 or 10 megs if you load 600 images, not to mention you're loading 600 freaking images.

Fast-forward to 2018, and there's the "Intersection Observer API" that's supported everywhere but Safari and IE, well, because, Safari and IE, sigh. We will return to that issue in a moment.

Following Dean Hume's blog post on the topic, I start with my images like this. I don't populate src="", but instead hold the Image URL in the HTML5 data- bucket of data-src. For src, I can use the nothing grey.gif or just style and color the image grey.

<a href="/626/christine-spangs-open-source-journey-from-teen-oss-contributor-to-cto-of-nylas" class="showCard">
    <img data-src="https://images.hanselminutes.com/images/626.jpg" 
         class="lazy" src="/images/grey.gif" width="212" height="212" alt="Christine Spang&#x27;s Open Source Journey from Teen OSS Contributor to CTO of Nylas" />
    <span class="shownumber">626</span>                
    <div class="overlay title">Christine Spang&#x27;s Open Source Journey from Teen OSS Contributor to CTO of Nylas</div>
</a>
<a href="/625/a-new-sega-megadrivegenesis-game-in-2018-with-1995-tools-with-tanglewoods-matt-phillips" class="showCard">
    <img data-src="https://images.hanselminutes.com/images/625.jpg" 
         class="lazy" src="/images/grey.gif" width="212" height="212" alt="A new Sega Megadrive/Genesis Game in 2018 with 1995 Tools with Tanglewood&#x27;s Matt Phillips" />
    <span class="shownumber">625</span>                
    <div class="overlay title">A new Sega Megadrive/Genesis Game in 2018 with 1995 Tools with Tanglewood&#x27;s Matt Phillips</div>
</a>

Then, if the images get within 50px intersecting the viewPort (I'm scrolling down) then I load them:

// Get images of class lazy
const images = document.querySelectorAll('.lazy');
const config = {
  // If image gets within 50px go get it
  rootMargin: '50px 0px',
  threshold: 0.01
};

let observer = new IntersectionObserver(onIntersection, config);
  images.forEach(image => {
    observer.observe(image);
  });

Now that we are watching it, we need to do something when it's observed.

function onIntersection(entries) {
  // Loop through the entries
  entries.forEach(entry => {
    // Are we in viewport?
    if (entry.intersectionRatio > 0) {

      // Stop watching and load the image
      observer.unobserve(entry.target);
      preloadImage(entry.target);
    }
  });
}

If the browser (IE, Safari, Mobile Safari) doesn't support IntersectionObserver, we can do a few things. I *could* fall back to my old jQuery technique, although it would involve loading a bunch of extra scripts for those browsers, or I could just load all the images in a loop, regardless, like:

if (!('IntersectionObserver' in window)) {
    loadImagesImmediately(images);
} else {...}

Dean's examples are all "Vanilla JS" and require no jQuery, no plugins, no polyfills WITH browser support. There are also some IntersectionObserver helper libraries out there like Cory Dowdy's IOLazy. Cory's is a nice simple wrapper and is super easy to implement. Given I want to support iOS Safari as well, I am using a polyfill to get the support I want from browsers that don't have it natively.

<!-- intersection observer polyfill -->
<script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=IntersectionObserver"></script>

Polyfill.io is a lovely site that gives you just the fills you need (or those you need AND request) tailored to your browser. Try GETting the URL above in Chrome. You'll see it's basically empty as you don't need it. Then hit it in IE, and you'll get the polyfill. The official IntersectionObserver polyfill is at the w3c.

At this point I've removed jQuery entirely from my site and I'm just using an optional polyfill plus browser support that didn't exist when I started my podcast site. Fewer moving parts means a cleaner, leaner, simpler site!

Go subscribe to the Hanselminutes Podcast today! We're on iTunes, Spotify, Google Play, and even Twitter!


Sponsor: Announcing Raygun APM! Now you can monitor your entire application stack, with your whole team, all in one place. Learn more!

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

A multi-player server-side GameBoy Emulator written in .NET Core and Angular

March 5, '18 Comments [4] Posted in Docker | DotNetCore | Javascript | Open Source
Sponsored By

Server-side GameBoyOne of the great joys of sharing and discovering code online is when you stumble upon something so truly epic, so amazing, that you have to dig in. Head over to https://github.com/axle-h/Retro.Net and ask yourself why this GitHub project has only 20 stars?

Alex Haslehurst has created some retro hardware libraries in open source .NET Core with an Angular Front End!

Translation?

A multiplayer server-side Game Boy emulator. Epic.

You can run it in minutes with

docker run -p 2500:2500 alexhaslehurst/server-side-gameboy

Then just browse to http://localhost:2500 and play Tetris on the original GameBoy!

I love this for a number of reasons.

First, I love his perspective:

Please check out my GameBoy emulator written in .NET Core; Retro.Net. Yes, a GameBoy emulator written in .NET Core. Why? Why not. I plan to do a few write-ups about my experience with this project. Firstly: why it was a bad idea.

  1. Emulation on .NET
  2. Emulating the GameBoy CPU on .NET

The biggest issue one has trying to emulate a CPU with a platform like .NET is the lack of reliable high-precision timing. However, he manages a nice from-scratch emulation of the Z80 processor, modeling low level things like registers in very high level C#. I love that public class GameBoyFlagsRegister is a thing. ;) I did similar things when I ported a 15 year old "Tiny CPU" to .NET Core/C#.

Address space diagram from https://ax-h.com/software/development/emulation/2017/12/03/emulating-the-gameboy-cpu-on-dot-net.html

Be sure to check out Alex's extremely detailed explanation on how he modeled the Z80 microprocessor.

Luckily the GameBoy CPU, a Sharp LR35902, is derived from the popular and very well documented Zilog Z80 - A microprocessor that is unbelievably still in production today, over 40 years after it’s introduction.

The Z80 is an 8-bit microprocessor, meaning that each operation is natively performed on a single byte. The instruction set does have some 16-bit operations but these are just executed as multiple cycles of 8-bit logic. The Z80 has a 16-bit wide address bus, which logically represents a 64K memory map. Data is transferred to the CPU over an 8-bit wide data bus but this is irrelevant to simulating the system at state machine level. The Z80 and the Intel 8080 that it derives from have 256 I/O ports for accessing external peripherals but the GameBoy CPU has none - favouring memory mapped I/O instead

He didn't just create an emulator - there's lots of those - but uniquely he runs it on the server-side while allowing shared controls in a browser. "In between each unique frame, all connected clients can vote on what the next control input should be. The server will choose the one with the most votes… most of the time." Massively multi-player online GameBoy! Then he streams out the next frame! "GPU rendering is completed on the server once per unique frame, compressed with LZ4 and streamed out to all connected clients over websockets."

This is a great learning repository because:

  • it has complex business logic on the server-side but the front end uses Angular and web-sockets and open web technologies.
  • It's also nice that he has a complete multi-stage Dockerfile that is itself a great example of how to build both .NET Core and Angular apps in Docker.
  • Extensive (thousands) of Unit Tests with the Shouldly Assertion Framework and Moq Mocking Framework.
  • Great example usages of Reactive Programming
  • Unit Testing on both server AND client, using Karma Unit Testing for Angular

Here's a few favorite elegant code snippets in this huge repository.

The Reactive Button Presses:

_joyPadSubscription = _joyPadSubject
    .Buffer(FrameLength)
    .Where(x => x.Any())
    .Subscribe(presses =>
                {
                    var (button, name) = presses
                        .Where(x => !string.IsNullOrEmpty(x.name))
                        .GroupBy(x => x.button)
                        .OrderByDescending(grp => grp.Count())
                        .Select(grp => (button: grp.Key, name: grp.Select(x => x.name).First()))
                        .FirstOrDefault();
                    joyPad.PressOne(button);
                    Publish(name, $"Pressed {button}");

                    Thread.Sleep(ButtonPressLength);
                    joyPad.ReleaseAll();
                });

The GPU Renderer:

private void Paint()
{
    var renderSettings = new RenderSettings(_gpuRegisters);

    var backgroundTileMap = _tileRam.ReadBytes(renderSettings.BackgroundTileMapAddress, 0x400);
    var tileSet = _tileRam.ReadBytes(renderSettings.TileSetAddress, 0x1000);
    var windowTileMap = renderSettings.WindowEnabled ? _tileRam.ReadBytes(renderSettings.WindowTileMapAddress, 0x400) : new byte[0];

    byte[] spriteOam, spriteTileSet;
    if (renderSettings.SpritesEnabled) {
        // If the background tiles are read from the sprite pattern table then we can reuse the bytes.
        spriteTileSet = renderSettings.SpriteAndBackgroundTileSetShared ? tileSet : _tileRam.ReadBytes(0x0, 0x1000);
        spriteOam = _spriteRam.ReadBytes(0x0, 0xa0);
    }
    else {
        spriteOam = spriteTileSet = new byte[0];
    }

    var renderState = new RenderState(renderSettings, tileSet, backgroundTileMap, windowTileMap, spriteOam, spriteTileSet);

    var renderStateChange = renderState.GetRenderStateChange(_lastRenderState);
    if (renderStateChange == RenderStateChange.None) {
        // No need to render the same frame twice.
        _frameSkip = 0;
        _framesRendered++;
        return;
    }

    _lastRenderState = renderState;
    _tileMapPointer = _tileMapPointer == null ? new TileMapPointer(renderState) : _tileMapPointer.Reset(renderState, renderStateChange);
    var bitmapPalette = _gpuRegisters.LcdMonochromePaletteRegister.Pallette;
    for (var y = 0; y < LcdHeight; y++) {
        for (var x = 0; x < LcdWidth; x++) {
            _lcdBuffer.SetPixel(x, y, (byte) bitmapPalette[_tileMapPointer.Pixel]);

            if (x + 1 < LcdWidth) {
                _tileMapPointer.NextColumn();
            }
        }

        if (y + 1 < LcdHeight){
            _tileMapPointer.NextRow();
        }
    }
    
    _renderer.Paint(_lcdBuffer);
    _frameSkip = 0;
    _framesRendered++;
}

The GameBoy Frames are composed on the server side then compressed and sent to the client over WebSockets. He's got backgrounds and sprites working, and there's still work to be done.

The Raw LCD is an HTML5 canvas:

<canvas #rawLcd [width]="lcdWidth" [height]="lcdHeight" class="d-none"></canvas>
<canvas #lcd
        [style.max-width]="maxWidth + 'px'"
        [style.max-height]="maxHeight + 'px'"
        [style.min-width]="minWidth + 'px'"
        [style.min-height]="minHeight + 'px'"
        class="lcd"></canvas>

I love this whole project because it has everything. TypeScript, 2D JavaScript Canvas, retro-gaming, and so much more!

const raw: HTMLCanvasElement = this.rawLcdCanvas.nativeElement;
const rawContext: CanvasRenderingContext2D = raw.getContext("2d");
const img = rawContext.createImageData(this.lcdWidth, this.lcdHeight);

for (let y = 0; y < this.lcdHeight; y++) {
  for (let x = 0; x < this.lcdWidth; x++) {
    const index = y * this.lcdWidth + x;
    const imgIndex = index * 4;
    const colourIndex = this.service.frame[index];
    if (colourIndex < 0 || colourIndex >= colours.length) {
      throw new Error("Unknown colour: " + colourIndex);
    }

    const colour = colours[colourIndex];

    img.data[imgIndex] = colour.red;
    img.data[imgIndex + 1] = colour.green;
    img.data[imgIndex + 2] = colour.blue;
    img.data[imgIndex + 3] = 255;
  }
}
rawContext.putImageData(img, 0, 0);

context.drawImage(raw, lcdX, lcdY, lcdW, lcdH);

I would encourage you to go STAR and CLONE https://github.com/axle-h/Retro.Net and give it a run with Docker! You can then use Visual Studio Code and .NET Core to compile and run it locally. He's looking for help with GameBoy sound and a Debugger.


Sponsor: Get the latest JetBrains Rider for debugging third-party .NET code, Smart Step Into, more debugger improvements, C# Interactive, new project wizard, and formatting code in columns.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

ASP.NET Single Page Applications Angular Release Candidate

January 8, '18 Comments [22] Posted in DotNetCore | Javascript
Sponsored By

I was doing some Angular then remembered that the ASP.NET "Angular Project Template" has a release candidate and is scheduled to release sometime soon in 2018.

Starting with just a .NET Core 2.0 install plus Node v6 or later, I installed the updated angular template. Note that this isn't the angular/react/redux templates that came with .NET Core's base install.

I'll start by adding the updated SPA (single page application) template:

dotnet new --install Microsoft.DotNet.Web.Spa.ProjectTemplates::2.0.0-rc1-final

Then from a new directory, just

dotnet new angular

Then I can open it in either VSCode or Visual Studio Community (free for Open Source). If you're interested in the internals, open up the .csproj project file and note the checks for ensuring node is install, running npm, and running WebPack.

If you've got the Angular "ng" command line tool installed you can do the usual ng related stuff, but you don't need to run "ng serve" because ASP.NET Core will run it automatically for you.

I set development mode with "SET ASPNETCORE_Environment=Development" then do a "dotnet build." It will also restore your npm dependencies as part of the build. The client side app lives in ./ClientApp.

C:\Users\scott\Desktop\my-new-app> dotnet build
Microsoft (R) Build Engine version 15.5 for .NET Core
Copyright (C) Microsoft Corporation. All rights reserved.

Restore completed in 73.16 ms for C:\Users\scott\Desktop\my-new-app\my-new-app.csproj.
Restore completed in 99.72 ms for C:\Users\scott\Desktop\my-new-app\my-new-app.csproj.
my-new-app -> C:\Users\scott\Desktop\my-new-app\bin\Debug\netcoreapp2.0\my-new-app.dll
v8.9.4
Restoring dependencies using 'npm'. This may take several minutes...

"dotnet run" then starts the ng development server and ASP.NET all at once.

My ASP.NET Angular Application

If we look at the "Fetch Data" menu item, you can see and example of how Angular and open source ASP.NET Core work together. Here's the Weather Forecast *client-side* template:

<p *ngIf="!forecasts"><em>Loading...</em></p>

<table class='table' *ngIf="forecasts">
<thead>
<tr>
<th>Date</th>
<th>Temp. (C)</th>
<th>Temp. (F)</th>
<th>Summary</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let forecast of forecasts">
<td>{{ forecast.dateFormatted }}</td>
<td>{{ forecast.temperatureC }}</td>
<td>{{ forecast.temperatureF }}</td>
<td>{{ forecast.summary }}</td>
</tr>
</tbody>
</table>

And the TypeScript:

import { Component, Inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Component({
selector: 'app-fetch-data',
templateUrl: './fetch-data.component.html'
})
export class FetchDataComponent {
public forecasts: WeatherForecast[];

constructor(http: HttpClient, @Inject('BASE_URL') baseUrl: string) {
http.get<WeatherForecast[]>(baseUrl + 'api/SampleData/WeatherForecasts').subscribe(result => {
this.forecasts = result;
}, error => console.error(error));
}
}

interface WeatherForecast {
dateFormatted: string;
temperatureC: number;
temperatureF: number;
summary: string;
}

Note the URL. Here's the back-end. The request is serviced by ASP.NET Core. Note the interface as well as the TemperatureF server-side conversion.

[Route("api/[controller]")]
public class SampleDataController : Controller
{
private static string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};

[HttpGet("[action]")]
public IEnumerable<WeatherForecast> WeatherForecasts()
{
var rng = new Random();
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
DateFormatted = DateTime.Now.AddDays(index).ToString("d"),
TemperatureC = rng.Next(-20, 55),
Summary = Summaries[rng.Next(Summaries.Length)]
});
}

public class WeatherForecast
{
public string DateFormatted { get; set; }
public int TemperatureC { get; set; }
public string Summary { get; set; }

public int TemperatureF
{
get
{
return 32 + (int)(TemperatureC / 0.5556);
}
}
}
}

Pretty clean and straightforward. Not sure about the Date.Now, but for the most part I understand this and can see how to extend this. Check out the docs on this release candidate and also note that this included updated React and Redux templates as well!


Sponsor: Scale your Python for big data & big science with Intel® Distribution for Python. Near-native code speed. Use with NumPy, SciPy & scikit-learn. Get it Today!

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

.NET and WebAssembly - Is this the future of the front-end?

August 12, '17 Comments [42] Posted in DotNetCore | Javascript | Open Source
Sponsored By

6 years ago Erik Meijer and I were talking about how JavaScript is/was an assembly language. It turned into an interesting discussion/argument (some people really didn't buy it) but it still kept happening. Currently WebAssembly world is marching forward and is supported in Chrome, Firefox, and in Development in Edge, Opera, and Safari.

"The avalanche has begun, it's too late for the pebbles to vote." - Ambassador Kosh

Today in 2017, WebAssembly is absolutely a thing and you can learn about it at http://webassembly.org. I even did a podcast on WebAssembly with Mozilla Fellow David Bryant (you really should check out my podcast, I'm very proud of it. It's good.)

The classic JavaScript TODO app, written with C# and .NET and Blazor

The image above is from Steve Sanderson's NDC presentation. He's writing the classic client-side JavaScript ToDo application...except he's writing the code in C#.

What is WebAssembly?

"WebAssembly or wasm is a low-level bytecode format for in-browser client-side scripting, evolved from JavaScript." You can easily compile to WebAssembly from C and C++ today...and more languages are jumping in to include WebAssembly as a target every day.

Since I work in open source .NET and since .NET Core 2.0 is cross-platform with an imminent release, it's worth exploring where WebAssembly fits into a .NET world.

Here's some projects I have identified that help bridge the .NET world and the WebAssembly world. I think that this is going to be THE hot space in the next 18 months.

WebAssembly for .NET

Despite its overarching name, this OSS project is meant to consume WASM binary files and execute them from within .NET assemblies. To be clear, this isn't compiling .NET languages' (C#, VB.NET, F#) into WebAssembly, this is for using WebAssembly as if it's any other piece of resuable compiled code. Got an existing WASM file you REALLY want to call from .NET? This is for that.

Interestingly, this project doesn't spin up a V8 or Chakra JavaScript engine to run WASM, instead it reads in the bytecode and converts them to .NET via System.Reflection.Emit. Interesting stuff!

Mono and WebAssembly

One of the great things happening in the larger .NET Ecosystem is that there is more than one ".NET" today. In the past, .NET was a thing that you installed on Windows and generally feared. Today, there's .NET 4.x+ on basically every Windows machine out there, there's .NET Core that runs in Docker, on Mac, Windows, and a dozen Linuxes...even Raspberry Pi, and Mono is another instance of .NET that allows you to run code in dozens of other platforms. There's multiple "instances of .NET" out there in active development.

The Mono Project has two prototypes using Mono and WebAssembly.

The first one uses the traditional full static compilation mode of Mono, this compiled both the Mono C runtime and the Mono class libraries along with the user code into WebAssembly code. It produces one large statically compiled application. You can try this fully statically compiled Hello World here. The full static compilation currently lives here.

So that's a totally statically compiled Hello World...it's all of Mono and your app into Web Assembly. They have another prototype with a difference perspective:

The second prototype compiles the Mono C runtime into web assembly, and then uses Mono’s IL interpreter to run managed code. This one is a smaller download, but comes at the expense of performance. The mixed mode execution prototype currently lives here.

Here they've got much of Mono running in Web Assembly, but your IL code is interpreted. One of the wonderful things about Computer Science - There is more than one way to do something, and they are often each awesome in their own way!

"Blazor" - Experimental UI Framework running .NET in the browser

With a similar idea as the Mono Project's second prototype, Steve Sanderson took yet another "instance of .NET," the six year old open source DotNetAnywhere (DNA) project and compiled it into Web Assembly. DNA was an interpreted .NET runtime written in portable C. It takes standard IL or CIL (Common Intermediate Language) and runs it "on resource-constrained devices where it is not possible to run a full .NET runtime (e.g. Mono)." Clever, huh? What "resource-constrained device do we have here six years later?" Why, it's the little virtual machine that could - the JavaScript VM that your browser already has, now powered by a standard bytecode format called WebAssembly.

To prove the concept, Steve compiles DotNetAnywhere to WASM but then takes it further. He's combined standard programming models that we see on the web with things like Angular, Knockoutjs, or Ember, except rather than writing your web applications' UI in JavaScript, you write in C# - a .NET language.

Here in the middle of some Razor (basically HTML with C# inline) pages, he does what looks like a call to a backend. This is C# code, but it'll run as WASM on the client side within a Blazor app.

@functions {
WeatherForecast[] forecasts;

override protected async Task InitAsync()
{
using (var client = new HttpClient())
{
var json = await client.GetStringAsync(AbsoluteUrl("/api/SampleData/WeatherForecasts"));
forecasts = JsonUtil.Deserialize<WeatherForecast[]>(json);
}
}
}

This would allow a .NET programmer to use the same data models on the client and the server - much like well-factored JavaScript should today - as well as using other .NET libraries they might be familiar or comfortable with.

Why do this insane thing? "To see how well such a framework might work, and how much anyone would care." How far could/should this go? David Fowler already has debugging working (again this is ALL prototypes) in Visual Studio Code. Don't take my word for it, watch the video as Steve presents the concept at the NDC Conference.

Blazor as a prototype has a number of people excited, and there was a Blazor Hackthon recently that produced some interesting samples including a full-blown app.

Other possibilities?

There's lots of other projects that are compiling or transpiling things to JavaScript. Could they be modified to support WebAssembly? You can take F# and compile it to JavaScript with F#'s Fable project, and some folks have asked about WebAssembly.

At this point it's clear that everyone is prototyping and hacking and enjoying themselves.

What do YOU think about WebAssembly?


Sponsor: Check out JetBrains Rider: a new cross-platform .NET IDE. Edit, refactor, test and debug ASP.NET, .NET Framework, .NET Core, Xamarin or Unity applications. Learn more and download a 30-day trial!

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb
Page 1 of 23 in the Javascript category Next Page

Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.