Getting Started with Blazor WebAssembly in ASP.NET Core 10

by Didin J. on Oct 19, 2025 Getting Started with Blazor WebAssembly in ASP.NET Core 10

Learn how to build and deploy a Blazor WebAssembly app with ASP.NET Core 10. Step-by-step guide to components, routing, data, and styling.

Blazor WebAssembly is a modern framework from Microsoft that allows developers to build interactive client-side web applications using C# instead of JavaScript. It runs directly in the browser via WebAssembly, a powerful low-level technology that enables near-native performance and secure sandboxed execution.

With Blazor WebAssembly, you can use the same language, libraries, and tools across both client and server, unifying your development stack under .NET. This eliminates the need to maintain separate codebases for frontend (JavaScript/TypeScript) and backend (C#) development.

Why Blazor WebAssembly?

  • C# Everywhere – Use C# for frontend logic, API calls, and data models.

  • Full .NET Ecosystem – Access .NET libraries and tools in the browser.

  • Component-Based Architecture – Build reusable, modular UI components.

  • Offline and Progressive Web App (PWA) Support – Run even without an internet connection.

  • Interoperability with JavaScript – Use existing JS libraries when needed.

Blazor WebAssembly vs. Blazor Server

Feature Blazor WebAssembly Blazor Server
Execution Runs in browser via WebAssembly Runs on server via SignalR
Latency Low (client-side) Depends on the network
Offline Support Yes No
Initial Load Time Larger (downloads runtime) Smaller
Scalability Excellent for many users Limited by server connections

What’s New in ASP.NET Core 10

ASP.NET Core 10 (part of .NET 10) introduces several enhancements for Blazor WebAssembly development:

  • Improved render performance for interactive components.

  • Enhanced JavaScript interop for better integration with modern front-end libraries.

  • Simplified hosting models that combine server and client-side rendering seamlessly.

  • Smaller runtime downloads for faster app startup.

  • New project templates that streamline setup and deployment.

By the end of this tutorial, you’ll have a solid understanding of how to create, build, and run your first Blazor WebAssembly app with ASP.NET Core 10, along with key concepts like components, routing, and data fetching.


Prerequisites

Before you dive into building your first Blazor WebAssembly app with ASP.NET Core 10, make sure your development environment is properly set up. This section covers everything you need to install and know before getting started.

System Requirements

You’ll need a machine capable of running .NET 10 SDK and your preferred code editor or IDE. The following platforms are supported:

  • Windows 10/11

  • macOS 12 or later

  • Linux (Ubuntu, Fedora, Debian, etc.)

Required Tools

  1. .NET 10 SDK
    Download and install the latest .NET 10 SDK from the official Microsoft website:
    👉 https://dotnet.microsoft.com/download
    To verify the installation, open a terminal or command prompt and run:

     
    dotnet --version

     

    You should see an output starting with 10. (e.g., 10.0.100).

  2. Visual Studio Code or Visual Studio 2025
    You can use any editor, but the following are recommended:

    • Visual Studio Code (cross-platform)
      Download: https://code.visualstudio.com/
      Make sure to install the C# Dev Kit extension for full Blazor support.

    • Visual Studio 2025 (Windows/macOS)
      Choose the ASP.NET and web development workload during installation.

  3. Modern Web Browser
    Use a browser that supports WebAssembly, such as:

    • Google Chrome

    • Microsoft Edge

    • Mozilla Firefox

    • Safari (latest version)

  4. Optional: Git
    If you plan to version control your code or push it to GitHub, install Git from:
    👉 https://git-scm.com/downloads

Basic Knowledge Requirements

This tutorial assumes you have:

  • A basic understanding of C# and .NET concepts

  • Familiarity with HTML and CSS

  • Some experience with web development (not required but helpful)

With your environment ready, you’re all set to create your first Blazor WebAssembly project and explore its structure.


Setting Up the Project

In this section, you’ll create and run your first Blazor WebAssembly app using ASP.NET Core 10. We’ll go step by step — from project creation to exploring the structure and understanding the default setup.

Step 1: Create a New Blazor WebAssembly Project

Open your terminal or command prompt, navigate to your desired workspace, and run the following command:

dotnet new blazorwasm -n BlazorWasmDemo

This command does the following:

  • Creates a new Blazor WebAssembly project named BlazorWasmDemo

  • Configures all required dependencies for a standalone Blazor client app

Once created, move into the project folder:

cd BlazorWasmDemo

Step 2: Run the Application

To make sure everything works, run the app with:

dotnet run

You’ll see output similar to:

info: Microsoft.Hosting.Lifetime[14]
      Now listening on: http://localhost:5267
info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
      Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
      Content root path: /Users/didin/ASPNETProjects/BlazorWasmDemo

Now, open your browser and navigate to the displayed URL (e.g., https://localhost:5267).

Getting Started with Blazor WebAssembly in ASP.NET Core 10 - blazerwasm

You should see the default Blazor WebAssembly welcome page — congratulations, your app is running! 🎉


Step 3: Explore the Project Structure

Let’s take a look at what was generated by the template. Your project folder should look like this:

BlazorWasmDemo/
│
├── Program.cs
├── wwwroot/
│   ├── css/
│   ├── favicon.ico
│   └── index.html
│
├── Pages/
│   ├── Counter.razor
│   ├── FetchData.razor
│   └── Index.razor
│
├── Shared/
│   ├── MainLayout.razor
│   └── NavMenu.razor
│
├── App.razor
├── Imports.razor
└── BlazorWasmDemo.csproj

Here’s what each part does:

Folder/File Description
Program.cs The entry point of your Blazor app — configures services and starts the WebAssembly host.
wwwroot/ The web root folder that contains static files like CSS, JS, and images.
Pages/ Contains Razor components that represent individual pages (routes).
Shared/ Stores shared UI components such as layouts or navigation menus.
App.razor The root component that sets up the router and defines the app structure.
Imports.razor Defines global namespaces that are available across all components.
.csproj Project configuration file — includes package references and build settings.

Step 4: Modify and Rebuild

Try changing the text in Pages/Home.razor:

@page "/"

<h1>Hello, Blazor WebAssembly!</h1>

<p>This is your first Blazor app powered by ASP.NET Core 10.</p>

Save the file and refresh your browser — your changes should appear instantly.

Getting Started with Blazor WebAssembly in ASP.NET Core 10 - updated home page

You’ve successfully set up your first Blazor WebAssembly project and explored its core structure.


Understanding Blazor Components

At the heart of every Blazor application are components. Components are the fundamental building blocks of the UI — they define layout, behavior, and logic. Each Blazor page, layout, and even reusable widget is a component written using Razor syntax, which combines C# and HTML seamlessly.

What is a Component?

A Blazor component is a .razor file that contains:

  • UI markup written in HTML

  • C# code that controls the logic and data

  • Optional CSS for styling

Components can be nested, reused, and parameterized — similar to React or Angular components.

Here’s a simple example of a custom component:

<!-- Greeting.razor -->
<h3>Hello, @Name!</h3>

@code {
    [Parameter]
    public string Name { get; set; } = "World";
}

You can then use this component inside another page like so:

<!-- Index.razor -->
@page "/"

<h1>Welcome to Blazor WebAssembly</h1>

<Greeting Name="Djamware" />

When you run the app, it will render:

Hello, Djamware!

Component Structure Explained

A typical component includes three key sections:

Section Purpose
Markup (HTML) Defines the UI layout and elements
Code Block (@code) Contains C# logic (properties, methods, event handlers)
Directives Special keywords starting with @ to control routing, imports, etc.

Example:

@page "/counter"

<h3>Counter</h3>

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

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

@code {
    private int count = 0;

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

When you click the button, the count variable updates instantly — no page reload required!
This reactive rendering is one of Blazor’s key strengths.

Component Lifecycle Methods

Blazor provides lifecycle methods (similar to Angular’s hooks or React’s lifecycle) that allow you to execute logic at specific times.
The most commonly used ones include:

Method Description
OnInitialized() Called once when the component is initialized.
OnParametersSet() Called each time component parameters are updated.
OnAfterRender() Called after the component has rendered.
Dispose() Called when the component is removed from the UI.

Example usage:

@code {
    protected override void OnInitialized()
    {
        Console.WriteLine("Component initialized");
    }
}

Passing Data Between Components

Blazor components communicate using parameters and event callbacks.

Example – parent to child:

<!-- Parent.razor -->
<ChildComponent Message="Hello from parent!" />
<!-- ChildComponent.razor -->
<h4>@Message</h4>

@code {
    [Parameter]
    public string Message { get; set; }
}

Example – child to parent via callback:

<!-- Parent.razor -->
<ChildComponent OnClick="HandleClick" />

@code {
    private void HandleClick()
    {
        Console.WriteLine("Button clicked in child component!");
    }
}
<!-- ChildComponent.razor -->
<button @onclick="OnClick">Click Me</button>

@code {
    [Parameter]
    public EventCallback OnClick { get; set; }
}

Best Practices for Components

  • Keep components small and focused on a single purpose.

  • Use parameters for input and callbacks for output.

  • Place reusable components in the Shared folder.

  • Use partial classes if you want to separate logic from markup (e.g., MyComponent.razor + MyComponent.razor.cs).

Now that you understand how Blazor components work, let’s move on to routing and navigation — how Blazor connects all these components into a seamless single-page app.


Adding Routing and Navigation

Blazor WebAssembly uses client-side routing to navigate between pages without reloading the browser. Each page in your app corresponds to a Razor component that has a @page directive defining its route. This allows your app to behave like a single-page application (SPA) while providing fast, smooth transitions.

How Routing Works in Blazor

Routing in Blazor is handled by the Router component, which is defined in App.razor.
Here’s what it looks like by default:

<Router AppAssembly="@typeof(App).Assembly" NotFoundPage="typeof(Pages.NotFound)">
    <Found Context="routeData">
        <RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)"/>
        <FocusOnNavigate RouteData="@routeData" Selector="h1" />
    </Found>
</Router>

This tells Blazor:

  • Use the current assembly (project) to find routes (AppAssembly)

  • Render the appropriate page based on the route (RouteView)

  • Apply a default layout (MainLayout)

  • Display a NotFound message when no route matches

Defining Routes in Pages

Each Blazor page (component) becomes routable when you add the @page directive at the top of the file.

For example:

<!-- Pages/Index.razor -->
@page "/"

<h1>Welcome to Blazor WebAssembly!</h1>
<!-- Pages/About.razor -->
@page "/about"

<h1>About This App</h1>
<p>This is a simple Blazor WebAssembly demo built with ASP.NET Core 10.</p>

Once defined, you can navigate to:

  • https://localhost:7160/ → loads Index.razor
  • https://localhost:7160/about → loads About.razor

Adding Navigation Links

Blazor provides the NavLink component for navigation, which works like HTML’s <a> tag but includes automatic active link styling.

You can add links in Layout/NavMenu.razor:

<!-- Layout/NavMenu.razor -->
<div class="nav flex-column">
    <NavLink href="/" Match="NavLinkMatch.All">
        <span class="oi oi-home"></span> Home
    </NavLink>
    <NavLink href="/about">
        <span class="oi oi-info"></span> About
    </NavLink>
</div>

When the user navigates, the current link will automatically get the CSS class active.

Dynamic Routes with Parameters

You can pass parameters through the route using curly braces {}.

Example:

<!-- Pages/Profile.razor -->
@page "/profile/{username}"

<h3>Profile Page</h3>
<p>Welcome, @username!</p>

@code {
    [Parameter]
    public string? username { get; set; }
}

Now you can visit:

https://localhost:5267/profile/Djamware

and it will display:

Welcome, Djamware!

Programmatic Navigation

You can also navigate between pages in C# using the NavigationManager service:

@inject NavigationManager Nav

<button class="btn btn-primary" @onclick="GoToAbout">Go to About</button>

@code {
    void GoToAbout()
    {
        Nav.NavigateTo("/about");
    }
}

This is useful for redirecting users after form submissions, authentication, or specific actions.

Custom Not Found Page

To provide a better user experience, you can customize the "Not Found" section in Pages/NotFound.razor:

@page "/not-found"
@layout MainLayout

<LayoutView Layout="@typeof(MainLayout)">
    <h3>404 - Page Not Found</h3>
    <p>Sorry, the page you’re looking for doesn’t exist.</p>
    <NavLink href="/">Back to Home</NavLink>
</LayoutView>

Now that routing and navigation are working, it’s time to connect your app to real data.


Working with Data and Services

One of the strengths of Blazor WebAssembly is its ability to consume and display real-time data — whether from APIs, databases, or local storage. Blazor uses dependency injection (DI) and services to handle data fetching and logic cleanly, keeping your components lightweight and focused on presentation.

In this section, you’ll learn how to:

  • Create and register a data service

  • Fetch data from a public API

  • Display data dynamically in a Blazor component

Step 1: Create a Data Model

Let’s start by creating a simple model to represent the data we’ll fetch.

For this example, we’ll use a public JSON API (https://jsonplaceholder.typicode.com/posts) that returns a list of posts.

Create a new folder named Models and add a file Post.cs:

// Models/Post.cs
namespace BlazorWasmDemo.Models
{
    public class Post
    {
        public int Id { get; set; }
        public int UserId { get; set; }
        public string? Title { get; set; }
        public string? Body { get; set; }
    }
}

Step 2: Create a Data Service

Next, we’ll create a service to handle HTTP requests using HttpClient.

Create a new folder named Services and add a file PostService.cs:

// Services/PostService.cs
using System.Net.Http.Json;
using BlazorWasmDemo.Models;

namespace BlazorWasmDemo.Services
{
    public class PostService
    {
        private readonly HttpClient _httpClient;

        public PostService(HttpClient httpClient)
        {
            _httpClient = httpClient;
        }

        public async Task<List<Post>> GetPostsAsync()
        {
            var posts = await _httpClient.GetFromJsonAsync<List<Post>>(
                "https://jsonplaceholder.typicode.com/posts"
            );
            return posts ?? new List<Post>();
        }
    }
}

This service uses HttpClient (built into Blazor) to fetch data asynchronously and return a list of posts.

Step 3: Register the Service

Open Program.cs and register the PostService with the dependency injection container:

using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using BlazorWasmDemo;
using BlazorWasmDemo.Services;

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) });
builder.Services.AddScoped<PostService>();

await builder.Build().RunAsync();

Now, the PostService is available for injection throughout your application.

Step 4: Create a Page to Display the Data

Create a new file named Posts.razor in the Pages folder:

@page "/posts"
@inject BlazorWasmDemo.Services.PostService PostService

<h3>Posts</h3>

@if (posts == null)
{
    <p><em>Loading...</em></p>
}
else
{
    <div class="list-group">
        @foreach (var post in posts)
        {
            <div class="list-group-item">
                <h5>@post.Title</h5>
                <p>@post.Body</p>
            </div>
        }
    </div>
}

@code {
    private List<BlazorWasmDemo.Models.Post>? posts;

    protected override async Task OnInitializedAsync()
    {
        posts = await PostService.GetPostsAsync();
    }
}

This component:

  • Injects the PostService

  • Loads data asynchronously in OnInitializedAsync()

  • Displays posts using a Bootstrap list group

Step 5: Add Navigation to the Posts Page

Open Layout/NavMenu.razor and add a link to the new page:

        <div class="nav-item px-3">
            <NavLink class="nav-link" href="/posts">
                <span class="oi oi-list"></span> Posts
            </NavLink>
        </div>

Save all changes, then run your app again:

dotnet run

Visit http://localhost:5267/posts — you should see a list of posts fetched from the JSONPlaceholder API.

Getting Started with Blazor WebAssembly in ASP.NET Core 10 - Posts list

Step 6: Handle Errors Gracefully

You can add error handling to improve reliability:

public async Task<List<Post>> GetPostsAsync()
{
    try
    {
        var posts = await _httpClient.GetFromJsonAsync<List<Post>>(
            "https://jsonplaceholder.typicode.com/posts"
        );
        return posts ?? new List<Post>();
    }
    catch (Exception ex)
    {
        Console.WriteLine($"Error fetching posts: {ex.Message}");
        return new List<Post>();
    }
}

This ensures your app won’t crash if the API is unreachable.

You’ve now learned how to inject services, fetch remote data, and display it dynamically in a Blazor WebAssembly app.


Styling and Layouts

A visually consistent layout and attractive styling make a big difference in any web application. In Blazor WebAssembly, you can style your app using CSS, Bootstrap, Tailwind, or even scoped component-specific styles. This section will show how to structure layouts, apply global and component-level styles, and integrate a CSS framework.

Understanding Layouts in Blazor

Layouts in Blazor are similar to master pages in ASP.NET MVC or templates in Angular — they define the common structure (like headers, footers, and navigation) shared across multiple pages.

By default, Blazor apps include a layout component called MainLayout.razor located in the Layout folder:

@inherits LayoutComponentBase
<div class="page">
    <div class="sidebar">
        <NavMenu />
    </div>

    <main>
        <div class="top-row px-4">
            <a href="https://learn.microsoft.com/aspnet/core/" target="_blank">About</a>
        </div>

        <article class="content px-4">
            @Body
        </article>
    </main>
</div>
  • @Body is where each page’s content gets rendered.

  • The NavMenu component provides navigation links.

  • The layout applies to all pages by default, as defined in App.razor.

Using Bootstrap for Styling

The Blazor WebAssembly template already includes Bootstrap (via wwwroot/css/bootstrap/).

To customize styles or add Bootstrap components, open wwwroot/index.html and ensure this link is present:

<link href="css/bootstrap/bootstrap.min.css" rel="stylesheet" />
<link href="css/app.css" rel="stylesheet" />

You can now use Bootstrap classes directly in your Razor files:

@page "/"

<h1 class="text-primary text-center">Welcome to Blazor WebAssembly</h1>

<div class="alert alert-success mt-3">
    <strong>Success!</strong> Your Blazor app is up and running.
</div>

This adds a clean, professional look instantly.

Customizing Global Styles

You can define global styles in wwwroot/css/app.css:

/* wwwroot/css/app.css */
body {
    font-family: "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
    background-color: #f8f9fa;
    color: #333;
}

h1, h3 {
    margin-top: 1rem;
}

These apply to the entire application.

Adding Component-Specific Styles

Blazor supports CSS isolation, which lets you scope styles to a specific component.
Simply create a .razor.css file next to your component.

For example, create Pages/Posts.razor.css:

/* Pages/Posts.razor.css */
.list-group-item {
    background-color: #fff;
    border: 1px solid #e0e0e0;
    margin-bottom: 10px;
    border-radius: 6px;
    transition: transform 0.2s ease;
}

.list-group-item:hover {
    transform: translateY(-3px);
    box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}

Blazor automatically scopes these styles to elements inside Posts.razor — no global conflicts!

Using Tailwind CSS (Optional)

If you prefer Tailwind CSS, you can integrate it easily for utility-first styling.

  1. Install Node.js (if not already): https://nodejs.org

  2. From your project root, run:

     
    npm init -y
    npm install tailwindcss postcss autoprefixer
    npx tailwindcss init

     

  3. Edit tailwind.config.js:

     
    module.exports = {
      content: ["./**/*.razor", "./wwwroot/index.html"],
      theme: { extend: {} },
      plugins: [],
    };

     

  4. In wwwroot/css/app.css, replace the contents with:

     
    @tailwind base;
    @tailwind components;
    @tailwind utilities;

     

  5. Build Tailwind styles:

     
    npx tailwindcss -i ./wwwroot/css/app.css -o ./wwwroot/css/output.css --watch

     

  6. Update index.html to use output.css:

     
    <link href="css/output.css" rel="stylesheet" />

     

Now you can use Tailwind classes directly:

<h1 class="text-3xl font-bold text-center text-blue-600">Hello Tailwind!</h1>

Adding a Footer Component

Let’s create a simple reusable footer.
Create a new file Layout/Footer.razor:

<footer class="text-center mt-4 py-3 border-top">
    <p>&copy; @DateTime.Now.Year - BlazorWasmDemo | Built with ASP.NET Core 10</p>
</footer>

Then include it in MainLayout.razor below @Body:

        <article class="content px-4">
            @Body
        </article>

        <Footer />

Now every page will have a consistent footer.

Your Blazor app now has a clean layout, responsive styling, and a modern look — ready for deployment or further customization.


Building and Running the App

Now that your Blazor WebAssembly app is complete, it’s time to run, test, and build it for production. Blazor WebAssembly compiles your C# code into WebAssembly and runs it directly in the browser — so everything happens client-side, without needing a .NET runtime installed on the client machine.

Running the App Locally

To start your application in development mode, open a terminal in your project directory and run:

dotnet run

Once the build completes, you’ll see output similar to:

info: Microsoft.Hosting.Lifetime[14]
      Now listening on: http://localhost:5267

Now, open your browser and navigate to the provided HTTPS URL (e.g., http://localhost:5267).

You should see your Blazor WebAssembly app running — complete with routing, navigation, and data fetched from the placeholder API.

💡 Tip: If you make changes to your .razor files, the app will automatically rebuild and refresh in the browser when running in development mode.

Building for Production

When you’re ready to deploy your Blazor WebAssembly app, you’ll need to build it in Release mode. This optimizes the output by minimizing and compressing your files.

Run the following command:

dotnet publish -c Release

This command generates your production-ready files in the bin/Release/net10.0/publish/wwwroot directory.

The output includes:

  • Compiled .dll files (your app and its dependencies)

  • A minimized index.html

  • A compressed blazor.webassembly.js loader

  • Static assets such as CSS, JavaScript, and images

Hosting the Blazor App

Blazor WebAssembly apps are static web applications, meaning you can host them on:

  • Azure Static Web Apps

  • GitHub Pages

  • Netlify

  • Vercel

  • Any static file server (like Nginx or Apache)

For example, to host it on Azure Static Web Apps, simply upload the wwwroot folder contents to your Azure storage or use the Azure CLI to deploy directly.

Testing the Deployment

Once deployed, open your hosted URL in a browser — your app should load instantly and function identically to your local build.

You can confirm everything is working by navigating between pages and checking that data from the API loads correctly.

Your Blazor WebAssembly App is Now Live!
You’ve just built and deployed your first Blazor WebAssembly app using ASP.NET Core 10. You now have a client-side app fully powered by C# and .NET — no JavaScript required.


Conclusion and Next Steps

Congratulations! 🎉
You’ve just built your first Blazor WebAssembly app with ASP.NET Core 10 — from project setup to component creation, routing, data fetching, and deployment.

Blazor WebAssembly empowers developers to build interactive web applications using C# and .NET, running entirely on the client side. This means you can write modern, single-page applications (SPAs) without needing to switch between multiple programming languages or frameworks like JavaScript or React.

What You Learned

In this tutorial, you learned how to:

  • Set up a Blazor WebAssembly project using .NET 10

  • Understand and build reusable Blazor components

  • Implement client-side routing and navigation

  • Fetch and display data from an API using dependency injection

  • Style your app using Bootstrap and shared layouts

  • Build and deploy your Blazor app for production

Next Steps

You’ve only scratched the surface of what Blazor can do. Here are some recommended next topics to explore:

  1. Authentication and Authorization
    Learn how to secure your Blazor apps using JWT tokens or ASP.NET Identity.

  2. Blazor with Web APIs
    Connect your Blazor frontend with a .NET 10 Web API for full-stack development.

  3. Real-Time Features with SignalR
    Add live chat, notifications, or dashboards using SignalR integration.

  4. Progressive Web Apps (PWA)
    Turn your Blazor app into a PWA that works offline and installs like a native app.

  5. Performance Optimization
    Explore ahead-of-time (AOT) compilation and lazy loading for faster performance.

By combining Blazor WebAssembly with the power of ASP.NET Core 10, you can build modern, scalable, and maintainable web apps — all in one unified .NET ecosystem.

You can find the full source code on our GitHub.

That's just the basics. If you need more deep learning about ASP.Net Core, you can take the following cheap course:

Thanks!