No More JavaScript: How Microsoft Blazor Uses WebAssembly
David Eastman explains how Microsoft has smoothed the path for WebAssembly. You'll be tempted to leave JavaScript behind after this.
Mar 27th, 2023 7:22am by
<code class="language-csharp">
@page "/counter"
<PageTitle>Counter</PageTitle>
<h1>Counter</h1>
<p role="status">Current count: @currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
@code {
private int currentCount = 0;
private void IncrementCount()
{
currentCount++;
}
}</code>
<code class="language-csharp">
@page "/counter"
@page "/counter/{startingValue:int}
<PageTitle>Counter</PageTitle>
<h1>Counter</h1>
<p role="status">Current count: @currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
@code {
private int currentCount = 0;
[Parameter]
public int StartingValue { get; set; }
protected override void OnParametersSet()
{
currentCount = StartingValue;
base.OnParametersSet();
}
private void IncrementCount()
{
currentCount++;
}
}</code>
This sets us up for the trickier binding of different types of HTML UI elements to C# code.
But for now, we will leave the Purple Man’s video lessons for a more pressing issue. This is the bit where we want to talk about the (purple) elephant in the room.
Are We Just Creating Server-Side Apps?
The answer is no. It is Microsoft’s business to create a unified development environment and blur the line between server-side and client-side. But they do make it clear they are different projects:
However, there are a few shiny but confusing baubles in the explanations for the two options above. WebAssembly directly supports .NET on the browser, and thus gives you offline behavior. In the Server App, no C# goes to the client at all. SignalR sounds like a toothpaste, but it is just asynchronous communication helper code for the client/server connection.
You may also have noticed that the last sentence in both descriptions is identical. Microsoft is trying to square off its older systems with ways to support modern techniques while protecting its platform legacy.
Differences Between the Server and Wasm Apps
I want to compare the differences in approach between a server and a WebAssembly-based app by looking at an example component. So what are the differences? The demo project I have been using is, under the hood, a Blazer Server. So let’s look at the simple FetchData example. It shows some fake weather:
On the backend is this a simple fake service in pure C#:
<code class="language-csharp">public class WeatherForecastService
{
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
public Task<WeatherForecast[]> GetForecastAsync(DateOnly startDate)
{
return Task.FromResult(Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = startDate.AddDays(index),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
}).ToArray());
}
}</code>
<code class="language-csharp">
@page "/fetchdata"
@using FirstBlazorApp.Data
@inject WeatherForecastService ForecastService
...</code>
<code class="language-csharp">
...
@code {
private WeatherForecast[]? forecasts;
protected override async Task OnInitializedAsync()
{
forecasts = await ForecastService.GetForecastAsync(DateOnly.FromDateTime(DateTime.Now));
}
}
</code>
<code class="language-csharp">
...
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();
builder.Services.AddSingleton<WeatherForecastService>();
...</code>
<code class="language-csharp">
@page "/fetchdata"
@inject HttpClient Http
...</code>
<code class="language-csharp">
@code {
private WeatherForecast[]? forecasts;
protected override async Task OnInitializedAsync()
{
forecasts = await Http.GetFromJsonAsync<WeatherForecast[]>("sample-data/weather.json");
}
...
}</code>
<code class="language-csharp">[
{
"date": "2022-01-06",
"temperatureC": 1,
"summary": "Freezing"
},
{
"date": "2022-01-07",
"temperatureC": 14,
"summary": "Bracing"
},
{
"date": "2022-01-08",
"temperatureC": -13,
"summary": "Freezing"
},
{
"date": "2022-01-09",
"temperatureC": -16,
"summary": "Balmy"
},
{
"date": "2022-01-10",
"temperatureC": -2,
"summary": "Chilly"
}
]</code>
<code class="language-csharp">...
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
builder.RootComponents.Add<HeadOutlet>("head::after");
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });</code>
YOUTUBE.COM/THENEWSTACK
Tech moves fast, don't miss an episode. Subscribe to our YouTube
channel to stream all our podcasts, interviews, demos, and more.