Tag: Code

Let’s talk Blazor!

Let’s talk Blazor!

You may or may not have heard of WebAssembly, or the Mono Framework, but Microsoft is blending them to wonderful platform goodness, for the future of the web. So, you may never need to understand either to take full advantage.

Keep in mind these are all experimental bits, at the moment. You can learn more at Blazor.net

WebAssembly (Wasm) is a part of all major modern browsers. It is a binary format for execution in a browser’s controlled sand-box. It is meant to be an intermediate format and not written directly, but it can be. In general you compile from a high level language to Wasm. It serves a similar purpose to JavaScript, but is not intended to be a replacement for JavaScript. In my opinion will take a large bite out of JavaScript’s stranglehold on client code; especially with Microsoft’s help.

The Mono framework was started in 2004. The .NET framework and compilers were Windows only. The Mono open-source project implemented the .NET APIs, based on the same ECMA-335 open standard, that was implemented in the official .NET. This allowed compiling and running .NET code on non-Windows systems, such as Linux and MacOS.

Blazor is an experimental Single-page application (SPA) framework that combines C#, WebAssembly, and Mono to allow C# code to be compiled and run directly in the browser. The Mono framework is provided as WebAssembly. For now, at least, the browser will use Mono to interpret the client .NET dll’s; but the speculation is that the compiler will eventually minify and cross-compile the .NET dll’s directly to WebAssembly.

Blazor has a deployment mode that is coded in mostly the same way, but runs server-side. The Blazor code runs on the server, and only the view differences are sent to the browser, via a SignalR connection. This mode gives the same coding benefits, but since the Blazor client code runs on the server, delays between the browser and server can be seen. It also requires more server compute power. This deployment mode is scheduled to be released in .NET Core 3.0.

For a Blazor coding experiment we will use the client side mode, with some WebApi to get configuration data. I made a simple dashboard with widgets that are loaded via server configuration. The project is based on the Hosted Blazor template.

Widgets can be any Blazor component, but I kept my widgets all cards to keep a consistent look.

There is a simple widget that just takes it content as parameters

There is a countdown widget, that can either countdown to a date, or count from one date to another with progress

There is a life countdown, to tell you how many more days you have to an age

And for fun there is a bouncing ball demo on a canvas

This is a simple demo, so the Blazor widgets are compiled directly into the client app, using pages. The index page will request an array of WidgetSettings from the server’s WebApi

WidgetSettings[] widgets;
protected override async Task OnInitAsync()
{
    widgets = await Http.GetJsonAsync<WidgetSettings[]>("api/SampleData/widgets");
    StateHasChanged();
}

The server currently returns a fixed list of widget settings, but could easily be extended to store and load these settings by the user.

[HttpGet("[action]")]
public IEnumerable<WidgetSettings> widgets()
{
    var widgets = new[]
    {
        new WidgetSettings() {widget = "LifeCountdown", parameters =  {{"Header","Jim"},{"BirthDay""1970/1/1"}, { "EndAge"70 }}},
        new WidgetSettings() {widget = "LifeCountdown", parameters =  {{"Header","Bob"},{"BirthDay""1990/7/4"},{ "EndAge"75 }}},
        new WidgetSettings() {widget = "LifeCountdown", parameters =  {{"Header","Rick"},{"BirthDay""1985/4/27"},{ "EndAge"80 }}},
        new WidgetSettings() {widget = "SimpleCard", parameters = {{"Header""This is a simple card"}, {"SubHeader"""},
            { "Body","This is the body of my simple card.  There are other simple cards, but this is mine."},
            { "colsLarge"6}, {"colsSmall"12}}},
        new WidgetSettings() {widget = "Countdown", parameters =
        {
            {"Header","Countdown to New Year" },
            {"From",$"{DateTime.Today.Year}/1/1"},
            {"To"$"{DateTime.Today.Year+1}/1/1"}
        }},
        new WidgetSettings() {widget = "Countdown", parameters =
        {
            {"Header","Countdown to July 4th" },
            {"From",$"{DateTime.Today.Year}/7/4"},
            {"To"$"{DateTime.Today.Year+1}/7/4"}
        }},
        new WidgetSettings() {widget = "CanvasWidget"}
    };
    return widgets;
}
 

These widgets are loaded to the Index page by using the builder, at runtime.

RenderFragment CreateDynamicComponent() => builder =>
{
    if (widgets == nullreturn;
 
    var assm = Assembly.GetExecutingAssembly();
    var assmName = assm.GetName().Name;
 
    foreach (var widget in widgets)
    {
        var widgetType = Type.GetType($"{assmName}.Widgets.{widget.widget}");
        if (widgetType != null)
        {
            AddWidget(builder, widgetType, widget.parameters);
        }
    }
};
 
private static void AddWidget(RenderTreeBuilder builder, Type widget, Dictionary<string,object> parameters )
{
    var seq = 0;
    builder.OpenComponent(seq, widget);
    foreach (var param in parameters)
    {
        seq++;
        builder.AddAttribute(seq, param.Key, param.Value);
    }
    builder.CloseComponent();
}

You can download the sample code here: https://github.com/jchristman75/BlazorDash