Front

Aspire Systems - internal use only

What's Blazor?

Mateusz
Turzyński

@page "/counter"

<h1>Counter</h1>

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

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

@code {
    private int currentCount = 0;

    private void IncrementCount()
    {
        currentCount++;
    }
}

?

App.dll

.NET

(mscorlib.dll, System.core.dll etc)

WebAssembly

(mono.wasm)

.cs

.razor

Compilation

What can Blazor do?

@page "/counter"

<h1>Counter</h1>

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

<InputNumber @bind="@currentCount" />

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

@code {
    private int currentCount = 0;

    private void IncrementCount()
    {
        currentCount++;
    }
}

A day in the life of a software developer

let's create a form :)

public class PersonModel
{
	[Required]
	[Range(18, 60, 
    	ErrorMessage = "Either too old or too young :(")]
	public int Age { get; set; }

	[Required]
	[MinLength(5)]
	[MaxLength(15)]
	public string FullName { get; set; }
    
	public string Password { get; set; }

	[Compare(nameof(Password))]
	public string RepeatPassword { get; set; }    
}
@inject HttpClient Http

@code {
    private PersonModel person = new PersonModel();
    
    private async Task HandleValidSubmit()
    {
        await Http.PostJsonAsync("/api", person);
    }

    private void HandleInvalidSubmit()
    {
        Console.WriteLine("The form is not valid :(");
    }
}
<EditForm Model="person"
          OnValidSubmit="@HandleValidSubmit"
          OnInvalidSubmit="@HandleInvalidSubmit">

    <DataAnnotationsValidator />
    <ValidationSummary />

    <h1>Personal form</h1>

    <p>
        <label>Enter your age:</label>
        <InputNumber @bind-Value="person.Age" />
    </p>
    <p>
        <label>Enter your name:</label>
        <InputText @bind-Value="@person.FullName" />
        <ValidationMessage For="@(() => person.FullName)" />
    </p>
    
    (...)
    
    <p>
        <button type="submit">Submit</button>
    </p>

</EditForm>

Style

<span>Colored span</span>

<div>Div with background</div>

<a href="#">Sample link with background</a>

<Styled>
    span {
        color: pink:
    }

    div {
        background: green;
        color: white;
    }

    a {
        background: blue;
    }
</Styled>

@code {}

Routing

@page "/simple-routing/{text}"
@page "/advanced-routing/{counter:int}"

<p>Text from parameter: @Text</p>
@if (Counter.HasValue)
{
    <p>Counter: @Counter</p>
}

@code {

    [Parameter]
    public string Text { get; set; }

    [Parameter]
    public int? Counter { get; set; }
}
<NavLink href="simple-form" 
         Match="NavLinkMatch.All" 
         class="nav-link">
    Simple form
</NavLink>
<NavLink href="simple-routing/test" 
         Match="NavLinkMatch.Prefix" 
         class="nav-link" >
    Simple routing
</NavLink>

Components

<div>

    <p>Hello @FullName</p>

    <button @onclick="OnDeleteAccount">
        Delete my account
    </button>

</div>

@code {

    [Parameter]
    public string FullName { get; set; }

    [Parameter]
    public EventCallback OnDeleteAccount { get; set; }
}
@page "/person"

@if (accountDeleted)
{
    <p>Account deleted</p>
}
else
{
    <PersonDetails FullName="John Rambo"
                   OnDeleteAccount="() => AccountDeleted()" />
}

@code {

    private bool accountDeleted;

    private void AccountDeleted()
    {
        accountDeleted = true;
    }
}

How do I talk to JavaScript?

JavaScript interop

// index.html
<script>
  window.getElementDimensions = selector => {
      try {
          const element = document.querySelector(selector);

          if (!element) {
              return null;
          }

          return {
              height: element.scrollHeight,
              width: element.scrollWidth
          };
      } catch (ex) {
          return null;
      }
  };
</script>
// UseJavaScript.razor
@inject IJSRuntime JSRuntime;

...

@code {
    class BrowserSize {
        public int Height { get; set; }
        public int Width { get; set; }
    }

    private string Selector { get; set; } = "body";
    private BrowserSize ClientSize { get; set; } = new BrowserSize();

    private async Task UpdateSize() 
    {
        var jsResult = await JSRuntime.InvokeAsync<BrowserSize>(
            "getElementDimensions", 
            Selector
        );

        ClientSize = jsResult != null ? jsResult : new BrowserSize();

        StateHasChanged();
    }
}

3rd party JS

// index.js
import { Chart } from 'chart.js';
import 'chartjs-plugin-labels';

export const charts = {
  drawChart: (canvasSelector, type, { data = [], labels = [] }) => {
    const canvas = document.querySelector(canvasSelector).getContext('2d');

    new Chart(canvas, {
      ....
    });
  }
};
const path = require('path');

module.exports = {
  module: {
    rules: [
      {
        test: /\.(js)$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader'
        }
      }
    ]
  },
  output: {
    path: path.resolve(__dirname, '../wwwroot/js'),
    filename: 'js-lib.js',
    library: 'FrontNetJS'
  }
};
@inject IJSRuntime JSRuntime;

<canvas id="chart-canvas"></canvas>

@code {
    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender) 
        {
            await InitializeChart();
        }
    }

    private async Task InitializeChart() 
    {
        await JSRuntime.InvokeVoidAsync("FrontNetJS.charts.drawChart", 
            "#chart-canvas", 
            "pie",
            new {
                Data = new List<int> { 100, 200, 300, 400},
                Labels = new List<string> { "A", "B", "C", "D" }
            }
        );
        StateHasChanged();
    }
}

Browser

UI Thread

Blazor

Blazor is single thread

What's Blazor?

it's a .NET runtime 

it's a SPA framework

Blazor Web Assembly is not yet production ready...

... in RC it's much better

Blazor Web Assembly is not yet production ready...

...but Blazor Server is

Blazor Server - How it works

JavaScript interop

Blazor WASM

  • runs client-side
  • heavy assets
  • no communication overhead
  • requires server-based API
  • doesn't require much server infrastructure

Blazor Server

  • runs server-side
  • light assets
  • generates heavy WS traffic
     
  • can act as an API server
     
  • doesn't scale well

vs

Where to use Blazor Web Assembly

Nowadays: nowhere

Future: SPA ( almost there)

Far future: performance-sensitive apps (see AoT) 

Where to use Blazor Server

Nowadays: intranet, dashboards

Future: probably is gonna disappear as soon as Blazor WASM is released

What's next?

  • Blazor Server - production ready
  • Blazor WASM - release candidate

Blazor PWA

Progressive Web Applications

Blazor Mobile Bindings

Native UI for mobile devices

<StackLayout>
    <Label FontSize="30"
           Text="@("You pressed " + count + " times")" />
    <Button Text="+1"
            OnClick="@HandleClick" />
</StackLayout>

@code {
    int count;

    void HandleClick()
    {
        count++;
    }
}

Q&A

[ASP] What is Blazor? - Front.net

By Mateusz Turzyński