Introduction
Blazor is a web UI framework from Microsoft that allows .NET developers to build interactive web applications using C#, .NET, HTML, and CSS.
Instead of writing application logic primarily in JavaScript, developers can use C# and Razor components to create reusable user interfaces. Depending on the Blazor hosting model and application configuration, code can run in the browser, on the server, or be rendered interactively using modern ASP.NET Core capabilities.
In this article, we will create a simple Blazor application step by step and build an interactive counter component. Along the way, we will understand Razor components, event handling, data binding, project structure, and how the application works.
What Is Blazor?
Blazor is Microsoft's framework for building web user interfaces with .NET.
A Blazor application is built from components. A component typically contains:
HTML markup for the UI.
C# code for application logic.
Razor syntax for combining markup and C#.
Event handlers for user interactions.
State that controls what is displayed.
For example, a button can call a C# method directly:
<button @onclick="IncrementCount">Click me</button>
@code {
private int currentCount = 0;
private void IncrementCount()
{
currentCount++;
}
}
When the user clicks the button, the IncrementCount method runs and the component updates its displayed state.
Blazor Hosting Models
Blazor has evolved with ASP.NET Core, so it is useful to understand the major hosting approaches.
Blazor WebAssembly
Blazor WebAssembly runs .NET code in the browser through WebAssembly.
The browser downloads the application and its required .NET runtime resources, after which supported application code can execute on the client.
This model is useful when an application requires substantial client-side execution.
Blazor Server
The original Blazor Server model executes components on the server. UI events are sent to the server and UI updates are communicated back to the browser over a real-time connection.
This reduces the amount of application code that needs to execute in the browser but requires a persistent connection between the client and server.
Blazor Web Apps
Modern ASP.NET Core also supports the Blazor Web App model, which allows developers to combine server-side rendering with interactive rendering modes.
This provides more flexibility when deciding which parts of an application need interactivity.
For new applications, the recommended project template depends on the .NET version and the application's requirements.
Prerequisites
Before creating the application, install the following:
A current supported .NET SDK.
Visual Studio 2022 with the appropriate ASP.NET and web-development workload, or Visual Studio Code with the C# tooling.
Basic knowledge of C#.
Basic knowledge of HTML.
You can verify the installed .NET SDK by running:
dotnet --version
The command should return the installed SDK version.
Creating Your First Blazor Application
There are several Blazor project templates available in modern .NET. The exact template options depend on the installed SDK version.
For a current Blazor Web App, you can create a project with:
dotnet new blazor -o BlazorDemoApp
Move into the project directory:
cd BlazorDemoApp
Then start the application:
dotnet run
The terminal will display the local address where the application is running.
Open that address in a browser to view the application.
Understanding the Project Structure
After creating the project, you will see several files and directories.
A typical Blazor project contains components, configuration files, static assets, and application startup code.
Some important areas include:
BlazorDemoApp
│
├── Components
│ ├── Layout
│ ├── Pages
│ └── App.razor
│
├── wwwroot
│
├── Program.cs
├── appsettings.json
└── BlazorDemoApp.csproj
The exact structure can vary between .NET versions and project templates.
Components
The Components directory contains Razor components used to build the application's user interface.
Pages
Application pages are implemented as Razor components and can be associated with routes.
For example:
@page "/counter"
This makes the component available at the /counter route.
wwwroot
The wwwroot directory contains static web assets such as:
Program.cs
Program.cs is responsible for application startup and service configuration.
In a Blazor Web App, it also configures the Razor component infrastructure and the application's HTTP pipeline.
Creating an Interactive Counter Component
Now let's build a simple interactive component.
Create or open a Razor component such as:
Components/Pages/Counter.razor
Add the following code:
@page "/counter"
<PageTitle>Counter</PageTitle>
<h1>Counter</h1>
<p role="status">Current count: @currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">
Click me
</button>
@code {
private int currentCount = 0;
private void IncrementCount()
{
currentCount++;
}
}
This example contains the main concepts of a basic Blazor component.
Understanding the Counter Code
The @page Directive
The following line defines the route:
@page "/counter"
When the application is configured for routing, navigating to /counter displays this component.
Displaying C# Data in HTML
The following markup displays the value of a C# variable:
<p role="status">Current count: @currentCount</p>
The @ symbol allows Razor syntax to transition from HTML markup to C# expressions.
Initially, currentCount is 0.
After the value changes, Blazor updates the relevant part of the UI.
Handling Button Clicks
The button uses:
@onclick="IncrementCount"
This connects the button's click event to the C# method:
private void IncrementCount()
{
currentCount++;
}
Every time the user clicks the button, the value increases by one.
Expected Output
When the /counter page is opened, the initial screen displays something similar to:
Counter
Current count: 0
[ Click me ]
After clicking the button once:
Counter
Current count: 1
[ Click me ]
After clicking it three more times:
Counter
Current count: 4
[ Click me ]
The important point is that no separate JavaScript function is required for this basic interaction. The event is handled by C# within the Razor component.
Adding a Reset Button
We can extend the component by adding another C# method.
@page "/counter"
<PageTitle>Counter</PageTitle>
<h1>Counter</h1>
<p role="status">Current count: @currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">
Increment
</button>
<button class="btn btn-secondary" @onclick="ResetCount">
Reset
</button>
@code {
private int currentCount = 0;
private void IncrementCount()
{
currentCount++;
}
private void ResetCount()
{
currentCount = 0;
}
}
Now the component has two user actions.
Increment
|
v
currentCount++
|
v
Updated UI
Reset
|
v
currentCount = 0
|
v
Updated UI
Understanding Component State
The currentCount variable represents component state.
private int currentCount = 0;
When an event changes the state, Blazor can render the component again so that the UI reflects the new value.
This state-driven approach is one of the important concepts behind component-based UI development.
For example:
Initial State
currentCount = 0
|
v
User clicks button
|
v
currentCount = 1
|
v
Component renders updated UI
Passing Data to a Component
Blazor components can also receive data from a parent component through parameters.
For example:
<h3>Hello, @Name!</h3>
@code {
[Parameter]
public string Name { get; set; } = string.Empty;
}
A parent component can provide the value:
<WelcomeMessage Name="Baibhav" />
The component then receives the value through its Name parameter.
This allows components to be reused with different data.
Creating a Reusable Component
One advantage of component-based development is reusability.
Suppose we create:
Components/Shared/WelcomeMessage.razor
with:
<div class="alert alert-info">
<h3>Welcome, @Name!</h3>
</div>
@code {
[Parameter]
public string Name { get; set; } = string.Empty;
}
The component can then be reused:
<WelcomeMessage Name="John" />
<WelcomeMessage Name="Sarah" />
<WelcomeMessage Name="David" />
The same component structure is used for all three users while the displayed value changes.
Data Binding in Blazor
Blazor also supports two-way data binding with the @bind directive.
For example:
<input @bind="name" />
<p>Hello, @name</p>
@code {
private string name = string.Empty;
}
When the user enters a value in the input field, the name variable is updated through the binding mechanism.
For example:
Input:
[ Khan ]
Output:
Hello, Khan
This is useful for forms, search fields, filters, and other interactive components.
Why Use Blazor?
Blazor can be a good choice for organizations and developers already working with the .NET ecosystem.
Some of its advantages include:
C# can be used for UI logic and application development.
Razor components encourage reusable UI design.
.NET libraries and tooling can be used across application layers.
ASP.NET Core integration is built into the platform.
Dependency injection is supported.
Authentication and authorization can be integrated with ASP.NET Core.
Developers can use familiar C# development tools and debugging workflows.
Blazor does not mean that JavaScript disappears from every application. JavaScript can still be used when browser APIs, existing JavaScript libraries, or third-party integrations require it.
Blazor and JavaScript
Blazor is designed to allow .NET developers to build interactive web UIs with C#, but JavaScript remains part of the web platform.
For example, an application may use JavaScript interoperability when it needs to call a browser API or an existing JavaScript library.
Blazor provides JavaScript interoperability through mechanisms commonly referred to as JS interop.
Therefore, the practical difference is not simply:
Blazor = No JavaScript
A more accurate description is:
Blazor = Build interactive UI primarily with .NET and C#
+
Use JavaScript when the application requires it
Common Beginner Mistakes
Using an Outdated Project Command
Blazor templates and hosting models have changed across .NET releases. A command that worked with an older .NET version may not represent the recommended project structure for a current application.
Always check the template available in the installed SDK:
dotnet new list blazor
Putting Too Much Code in One Component
Components should have a clear responsibility. Large components become difficult to understand and maintain.
When a UI section becomes complex, consider extracting it into a reusable component.
Confusing Component State and Application State
A private field inside a component is suitable for local component state, but shared application state may require a different design.
Do not put all application data into a single component simply because it is easy to access.
Assuming JavaScript Is Never Required
Blazor reduces the need to write JavaScript for many UI scenarios, but browser applications can still require JavaScript interoperability.
A Simple Blazor Development Workflow
A beginner can follow this workflow when starting a Blazor project:
Create Project
|
v
Create Razor Component
|
v
Add HTML Markup
|
v
Add C# State
|
v
Handle User Events
|
v
Run Application
|
v
Test in Browser
|
v
Extract Reusable Components
This approach helps developers learn the framework without introducing unnecessary complexity.
Conclusion
Blazor provides a way to build interactive web interfaces using C#, .NET, Razor syntax, and reusable components.
In this tutorial, we created a Blazor application, examined its project structure, built an interactive counter, handled button events, worked with component state, created reusable components, and explored data binding.
The key concept to remember is that a Blazor application is built from components. Each component can contain markup, state, parameters, and event-handling logic, making it possible to create interactive web interfaces while staying within the .NET development ecosystem.
Once these fundamentals are understood, the next steps are to explore forms and validation, dependency injection, routing, authentication and authorization, API integration, component lifecycle methods, and application state management.
Join the conversation! Your thoughts help the community grow.