Skip to content

Instantly share code, notes, and snippets.

View SteveSandersonMS's full-sized avatar

Steve Sanderson SteveSandersonMS

View GitHub Profile
@SteveSandersonMS
SteveSandersonMS / blazor-error-handling.md
Last active April 10, 2024 13:26
Error handling in Server-Side Blazor

Error handling in Server-Side Blazor

Developers building Blazor applications should be aware of how the framework deals with exceptions, and what steps to take in order to maximize reliability and to detect and diagnose errors.

To recap, server-side Blazor is a stateful framework. For as long as users are interacting with your application, they maintain a connection to the server known as a circuit. The circuit holds all the active component instances, plus many other aspects of state such as the components' most recent render output and the current set of event-handling delegates that could be triggered by client-side events. If a user opens your application in multiple browser tabs, then they have multiple independent circuits.

As a high-level principle, Blazor treats most unhandled exceptions as fatal to that circuit. If a circuit is terminated due to an unhandled exception, the user can only continue by reloading the page to create a new circuit and starting again, although other circuits (e.g., th

@SteveSandersonMS
SteveSandersonMS / blazor-auth.md
Created June 11, 2019 10:49
Blazor authentication and authorization

Authentication and Authorization

Authentication means determining who a particular user is. Authorization means applying rules about what they can do. Blazor contains features for handling both aspects of this.

It worth remembering how the overall goals differ between server-side Blazor and client-side Blazor:

  • Server-side Blazor applications run on the server. As such, correctly-implemented authorization checks are both how you determine which UI options to show (e.g., which menu entries are available to a certain user) and where you actually enforce access rules.
  • Client-side Blazor applications run on the client. As such, authorization is only used as a way of determining what UI options to show (e.g., which menu entries). The actual enforcement of authorization rules must be implemented on whatever backend server your application operates on, since any client-side checks can be modified or bypassed.

Authentication-enabled templates for Server-Side Blazor

@SteveSandersonMS
SteveSandersonMS / blazor-state-user-docs.md
Last active February 29, 2024 02:46
Preserving State in Server-Side Blazor applications

Preserving State in Server-Side Blazor applications

Server-side Blazor is a stateful application framework. Most of the time, your users will maintain an ongoing connection to the server, and their state will be held in the server's memory in what's known as a "circuit". Examples of state held for a user's circuit include:

  • The UI being rendered (i.e., the hierarchy of component instances and their most recent render output)
  • The values of any fields and properties in component instances
  • Data held in DI service instances that are scoped to the circuit

Occasionally, users may experience a temporary network connection loss, after which Blazor will attempt to reconnect them to their original circuit so they can continue.

@SteveSandersonMS
SteveSandersonMS / Customer.cs
Created September 4, 2019 10:48
Blazor + FluentValidation example
public class Customer
{
public string FirstName { get; set; }
public string LastName { get; set; }
public Address Address { get; } = new Address();
public List<PaymentMethod> PaymentMethods { get; } = new List<PaymentMethod>();
}
public class Address
{
@SteveSandersonMS
SteveSandersonMS / sequence-number.md
Last active November 28, 2023 20:28
Why sequence numbers should relate to code line numbers, not execution order

Why sequence numbers should relate to code line numbers, not execution order

Or in other words, why you should hard-code sequence numbers, and not generate them programmatically.

Unlike .jsx files, .razor/.cshtml files are always compiled. This is potentially a great advantage for .razor, because we can use the compile step to inject information that makes things better or faster at runtime.

A key example of this are sequence numbers. These indicate to the runtime which outputs came from which distinct and ordered lines of code. The runtime uses this information to generate efficient tree diffs in linear time, which is far faster than is normally possible for a general tree diff algorithm.

Example

using System;
using System.Threading.Tasks;
namespace Microsoft.AspNetCore.Components
{
public class SectionContent : IComponent, IDisposable
{
private SectionRegistry _registry;
[Parameter] public string Name { get; set; }
@SteveSandersonMS
SteveSandersonMS / Index.razor
Created February 20, 2020 14:24
Blazor WebAssembly use of ClientWebSocket
@page "/"
@using System.Net.WebSockets
@using System.Text
@using System.Threading
@implements IDisposable
<h1>Echo test</h1>
<h3>State: @webSocket.State</h3>
@if (webSocket.State == WebSocketState.Open)

Cross-component interactions

Blazor should make it easy to build all the classic high-level UI widgets, such as forms, grids, tabs, dialogs, and so on. One of the big technical pieces needed for this is templated components, and since 0.6.0 we have strong support for that. Another necessary bit of infrastructure is a mechanism for components to collaborate based on ancestor/descendant relationships. For example:

  • In a Form component, you'd want nested Input components to be able to affect the form's validation on submit.
  • In a TabSet component, you'd want the TabSet to discover nested Tab components so it knows what tab titles to display, and to render only the active one (either by TabSet choosing which child to render, or by Tab knowing whether it's currently the active one).
  • In a NavBar component, you'd want a HamburgerButton component to be able to send a "toggle expansion" signal to the NavBar.

As of today, all these are possible but only through manual wiring. For exa

@SteveSandersonMS
SteveSandersonMS / stub-wasi.c
Created April 21, 2023 10:26
Eliminate WASI imports
#include <wasi/api.h>
#include <stdlib.h>
// Based on https://github.com/WebAssembly/wasi-libc/blob/main/libc-bottom-half/sources/__wasilibc_real.c,
int32_t __imported_wasi_snapshot_preview1_args_get(int32_t arg0, int32_t arg1) { return 0; }
int32_t __imported_wasi_snapshot_preview1_args_sizes_get(int32_t arg0, int32_t arg1) { return 0; }
int32_t __imported_wasi_snapshot_preview1_environ_get(int32_t arg0, int32_t arg1) { return 0; }
@SteveSandersonMS
SteveSandersonMS / GridSample.razor
Created March 16, 2023 16:18
Grid with columns in method
@page "/"
@using Microsoft.AspNetCore.Components.QuickGrid
<label>
<input @bind="@showName" type="checkbox" />
Show name
</label>
<QuickGrid Items="@people">
@Columns()