Isaac.

Blazor WebAssembly

Build client-side web apps with C# and WebAssembly.

By EMEPublished: February 20, 2025
blazorwebassemblycsharpclient-sidespa

A Simple Analogy

Blazor WebAssembly is like shipping your .NET app directly to the browser. The entire app runs locally, downloading once then working offline.


What Is Blazor WebAssembly?

Blazor WebAssembly compiles C# to WebAssembly, running in the browser just like JavaScript. Full .NET runtime in the browser—no server needed for UI.


Why Use Blazor WebAssembly?

  • No server calls: Runs entirely in browser
  • Offline capable: Works without network
  • Fast after load: No latency on interactions
  • C# everywhere: Same language client and server
  • Native .NET: Use LINQ, reflection, etc.

Program.cs

var builder = WebAssemblyHostBuilder.CreateDefault(args);

builder.RootComponents.Add<App>("#app");
builder.RootComponents.Add<HeadOutlet>("head::after");

// Register services
builder.Services.AddScoped(sp => 
    new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });

builder.Services.AddScoped<IOrderService, OrderService>();

await builder.Build().RunAsync();

Component Example

// Pages/Products.razor
@page "/products"
@inject IProductService ProductService
@inject HttpClient Http

<h1>Products</h1>

@if (products == null)
{
    <p>Loading...</p>
}
else
{
    <table class="table">
        <thead>
            <tr>
                <th>Name</th>
                <th>Price</th>
            </tr>
        </thead>
        <tbody>
        @foreach (var product in products)
        {
            <tr>
                <td>@product.Name</td>
                <td>@product.Price</td>
            </tr>
        }
        </tbody>
    </table>
}

@code {
    private List<Product> products;

    protected override async Task OnInitializedAsync()
    {
        // Load from API
        products = await Http.GetFromJsonAsync<List<Product>>("/api/products");
    }
}

HTTP Calls

public class OrderService
{
    private readonly HttpClient _http;
    
    public async Task<Order> GetOrderAsync(int id)
    {
        return await _http.GetFromJsonAsync<Order>($"/api/orders/{id}");
    }
    
    public async Task CreateOrderAsync(Order order)
    {
        var response = await _http.PostAsJsonAsync("/api/orders", order);
        response.EnsureSuccessStatusCode();
    }
}

Authentication

// Program.cs
builder.Services.AddAuthorizationCore();
builder.Services.AddCascadingAuthenticationState();
builder.Services.AddScoped<AuthenticationStateProvider, PersistentAuthenticationStateProvider>();

// Component
@page "/secure"
@attribute [Authorize]

<h1>Secure Page</h1>
<p>Only authenticated users see this</p>

@code {
    [CascadingParameter]
    private Task<AuthenticationState> authenticationStateTask { get; set; }
}

Best Practices

  1. Lazy load: Download only needed code
  2. Minimize bundle: Exclude unused libraries
  3. Use APIs: Call backend for data
  4. Optimize rendering: Cache components
  5. Error handling: Catch exceptions gracefully

Related Concepts

  • Progressive Web Apps (PWA)
  • IndexedDB for client storage
  • Web Workers for background tasks
  • Interop with JavaScript

Summary

Blazor WebAssembly brings .NET to the browser, enabling offline-capable, highly interactive single-page applications without JavaScript.