Blazor
Blazor
Section titled “Blazor”Client - Server
Section titled “Client - Server”Web Applications consist of a server-component and a client-component.

Client - Server (2)
Section titled “Client - Server (2)”The business logic of a web application is primarily implemented on the server.
Clients are primarily used for presenting data and for user interaction.
Frontend - Backend
Section titled “Frontend - Backend”Server components are also commonly referred to as Backend.
Client components are also commonly referred to as Frontend.
Categorizing Blazor
Section titled “Categorizing Blazor”Blazor is a Frontend-technology for the ASP.NET Core Framework.
Both Blazor and ASP.NET Core are created and maintained by Microsoft. Whereas ASP.NET Core is for creating web applications in general, Blazor fills the role of creating frontend applications within the ASP.NET Core ecosystem.
Frontend technologies
Section titled “Frontend technologies”Basic technologies that are used to create web frontends are Javascript, HTML and CSS.
- HTML
- is the structure of the UI.
- CSS
- is for styling the elements defined with HTML.
- JavaScript
- is for adding dynamic logic using a programming language.
Blazor SSR
Section titled “Blazor SSR”Blazor in .NET 8 uses primarily server-side rendering (SSR) to deliver websites.
When the client requests a page, an HTTP request is sent to the server. The server calculates what needs to be rendered according to the client’s request and sends back HTML, CSS and JavaScript files to the client, where they will be presented to the user.
Blazor SSR (2)
Section titled “Blazor SSR (2)”When using SSR with Blazor you are very limited in reacting to user interaction.
For every action the user performs on the client, a request needs to be sent to the server, where the server processes the information and sends back the response as a new page, consisting of HTML, CSS and JavaScript.
Blazor User Interaction
Section titled “Blazor User Interaction”When you want to allow more sophisticated forms of user interaction and (partial) view updates without the need to perform a server request in between you need to choose one of the following:
- Implement client logic with JavaScript
- Use InteractiveServer render mode
- Use InteractiveWebAssembly render mode
JavaScript Client logic
Section titled “JavaScript Client logic”You can of course add JavaScript files to a Blazor project and implement dynamic logic on the client with it.
However, if you wanted to use JavaScript from the beginning, Blazor is probably not the correct technology for you to use. (Choose Angular, React, Vue, jQuery, … instead)
Blazor is primarily meant as a technology that uses C# for implementing client logic.
WebAssembly
Section titled “WebAssembly”WebAssembly is a special Bytecode that can be executed inside the browser.
Together with JavaScript these two languages are the only ones understood by the browser.
A Bytecode is usually not written by humans, but compiled from a higher programming language.
WebAssembly (2)
Section titled “WebAssembly (2)”Using WebAssembly it is possible to convert, or (cross-)compile the source code of a higher programming language (Java, C, C++, C#) and execute them in the browser.
Bytecode shouldn’t be confused with machine code. Machine code is directly executed on a processor, whereas Bytecode is interpreted by an interpreter.
Webassembly vs. Typescript
Section titled “Webassembly vs. Typescript”
Blazor WASM
Section titled “Blazor WASM”
Blazor WASM
Section titled “Blazor WASM”Blazor ships a WASM-compiled .NET Runtime to the browser.
It then sends the compiled razor views and dependencies as dll files to the browser. The browser can execute the code inside by using the .NET Runtime.
We effectively taught the browser how to understand and execute C# code.
Blazor Server
Section titled “Blazor Server”
Blazor Server (2)
Section titled “Blazor Server (2)”When using the InteractiveServer render mode with Blazor, the server opens a websocket connection to the client. Any user interaction will be sent to the server via this connection. The server computes the necessary UI changes and sends back to the client what needs to be updated.
The underlying technology used to send data via the websocket connection is SignalR.
SignalR is a nuget package that can be used separately from Blazor to implement real-time communication between client and server using websockets.
Blazor
Section titled “Blazor”Blazor is a Framework for creating interactive user interfaces for web applications.
Blazor can therefore be compared with technologies such as Angular or React.

Blazor Motivation
Section titled “Blazor Motivation”When using Blazor …
- both frontend and backend of an application can be implemented using a single technology (.NET)
- you can use .NET languages (C#, F#) instead of JavaScript
Razor Pages
Section titled “Razor Pages”Blazor applications are built up using Razor Pages.
Razor is a templating engine (similar to PHP) where you can mix static HTML with C# code to implement dynamic views (e.g. render a certain element based on a condition).
HTML and code
Section titled “HTML and code”HTML is the structure of your application.
Use C# code to add logic to it.
<h1>Hallo @name!</h1>@code { string name = "Hugo";}Razor code
Section titled “Razor code”To implement logic inside your Razor Pages you can use Razor expressions.
There are 3 types of Razor expressions:
- Razor expression
- Razor code block
- Razor control structure
Detailed info: Razor expression docs
Razor expressions
Section titled “Razor expressions”Razor expressions will be evaluated to a value upon execution.
There are 2 forms:
- implicit Razor expressions
- explicit Razor expressions
Implicit Razor expressions
Section titled “Implicit Razor expressions”An implicit Razor expression starts with the @ symbol, followed by an expression. The @ symbol tells Razor to start evaluating C# code.
You can use implicit Razor expressions to access values of variables.
<span>Zeitpunkt: @DateTime.Now </span><span>Hallo @CustomToUpper(Name) </span>
@code { public string Name { get; set; } = "Hugo";
string CustomToUpper(string value) => value.ToUpper();}Explicit Razor expressions
Section titled “Explicit Razor expressions”An explicit Razor expression starts with the @ symbol, followed by an expression surrounded by parentheses.
You need to use explicit Razor expressions when the parser cannot infer the syntax of the expression correctly.
<span>Ergebnis: 2 + 2 = @(2 + 2) </span>Razor code blocks
Section titled “Razor code blocks”A Razor Code Block starts with the phrase @code followed by program definitions (classes, methods, variables) surrounded by braces.
Whereas Razor expressions will always be evaluated to a value, code blocks aren’t meant to be rendered.
<span>Hallo @CustomToUpper(Name) </span>
@code { public string Name { get; set; } = "Hugo";
string CustomToUpper(string value) => value.ToUpper();}Razor control structures
Section titled “Razor control structures”Razor control structures are an extension of code blocks.
They are meant to control the program execution within Razor Pages.
Control structure: if
Section titled “Control structure: if”@if(names.Length > 0) { <span>We have friends: @names.Length</span>} else { <span>Lets buy a dog!</span>}
@code { string[] names = {"Tobi", "Nikolei", "Franz"};}Control structure: switch
Section titled “Control structure: switch”@switch(index) { case 200: <p>OK</p> break; case 404: <p>Not Found</p> break: default: <p>code is wrong</p> break;}
@code { int code = 404;}Control structure: for
Section titled “Control structure: for”@for(var i = 0; i < persons.Length; i++) { var person = persons[i]; <p>Name: @person.Name</p> <p>Age: @person.Age</p>}
@code { Person[] persons = { // ... };}Control structure: foreach
Section titled “Control structure: foreach”@foreach(var person in persons) { <p>Name: @person.Name</p> <p>Age: @person.Age</p>}
@code { Person[] persons = { // ... };}Single Page Application
Section titled “Single Page Application”SPAs are web applications, that consist of a single HTML page.
Contents of the website are loaded dynamically and on-demand.
SPA - Communication
Section titled “SPA - Communication”Internally, SPAs don’t use navigation between websites.
The presentation flow is not interrupted, because no complete pages have to be loaded and rendered. Only parts of the application are reloaded as needed.
WA vs. SPA
Section titled “WA vs. SPA”
WA vs. SPA (2)
Section titled “WA vs. SPA (2)”
SPA Advantages
Section titled “SPA Advantages”
Components
Section titled “Components”Components are the building blocks of an SPA.
At runtime components are being loaded and disposed. The page in which the components are rendered stays the same.
Razor Components
Section titled “Razor Components”Blazor applications consist of Razor components .
Razor components are a mixture of HTML and program code (C#). Razor components are being compiled to C# classes.
Razor Components - Example
Section titled “Razor Components - Example”<!-- ----------------------------------------------- --><!-- Component: Card<!-- ----------------------------------------------- --><div class="card"> <div class="card-body"> <h3 class="card-title">@Movie.Title</h3> <p class="small">@Movie.Description</p> </div></div>@code { [Parameter] public Movie Movie { get; set; }}Using Razor Components
Section titled “Using Razor Components”<!-- ----------------------------------------------- --><!-- Using the Card component<!-- ----------------------------------------------- --> ... <div class="col"> <div class="caed-deck"> <Card Movie="@MovieCard"/> </div> </div>...@code{ Movie MovieCard { get; set; }}Component Lifecycle
Section titled “Component Lifecycle”When a component loads, a couple of methods are being called on the component by the framework.
These methods are called lifecycle methods.
Every Razor component inherits from ComponentBase in which these lifecycle methods are defined.
Lifecycle methods
Section titled “Lifecycle methods”<div> ... </div>@code { protected override Task SetParametersAsync( ParameterView parameters ) {...} protected override void OnInitialized() {...} protected override async Task OnInitializedAsync() {...} protected override void OnParametersSet() {...} protected override async Task OnParametersSetAsync() {...} protected override void OnAfterRender( bool firstRender ) {...}}Lifecycle methods - Execution order
Section titled “Lifecycle methods - Execution order”<div> ... </div>@code { (1) protected o. Task SetParametersAsync( ParameterView parameters ) {...} (2) protected o. async Task OnInitialized() {...} (3) protected o. async Task OnParametersSet() {...} (4) protected o. async Task OnAfterRender( bool firstRender ) {...}}SetParametersAsync
Section titled “SetParametersAsync”<div> ... </div>@code { /* * This method is called when the parameters * for the component are being loaded. * You can intercept the parameters and * do actions based on them. */ protected override Task SetParametersAsync( ParameterView parameters) {...} }OnInitializedAsync
Section titled “OnInitializedAsync”<div> ... </div>@code { /* * This method is called so you can initialize * the internal fields of the component. * Use this instead of a constructor. */ protected override Task OnInitialisedAsync() {...}}OnParametersSetAsync
Section titled “OnParametersSetAsync”<div> ... </div>@code {/** This method is called when parameters are changed.*/ protected override Task OnParametersSetAsync() {...}}OnAfterRenderAsync
Section titled “OnAfterRenderAsync”<div> ... </div>@code { /* * This method is called, after the component * has been rendered on the page. */ protected override Task OnAfterRenderAsync() {...}}Sending data up
Section titled “Sending data up”Parameters are used to send values from parent components to child components.
<!-- Card Component receives parameter Movie --><Card Movie="@Movie"/>To send data up from a child component to a parent component you can use event handlers.
<h3>MyComponent</h3>
<input type="text" @bind-value="message"></input><button @onclick="OnUpdateClick">Update</button>
@code { [Parameter] public EventCallback<string> OnValueChanged { get; set; } private string message = "";
private void OnUpdateClick() { OnValueChanged.InvokeAsync(message); }}To receive data from a child component in a parent component, simply register an event handler:
<MyComponent OnValueChanged="Callback" />
@code { private void Callback(string messageFromChild) { // TODO }}Navigation
Section titled “Navigation”In Blazor there are 2 kinds of components:
- Razor Page
- Razor Component
Page Directive
Section titled “Page Directive”Razor Pages are components that can be loaded explicitly via a URL.
Use the @page directive to make a page out of a component.
@page "/hallo"<div>...</div>@code { ...}Path Variables
Section titled “Path Variables”Blazor allows passing parameter values as part of the path in the URL.
Per default, string will be used as the type for parameters.
@page "/people/{Message}"<div> ... <h2>@Message</h2></div>@code { [Parameter] public string Message { get; set; }}Path variables - Data Types
Section titled “Path variables - Data Types”You can explicitly set different data types when you don’t want to use a string for path variables.
@page "/people/{Id:int}"<div>...</div>@code { [Parameter] public int Id { get; set; }}Path variables - Multiple routes
Section titled “Path variables - Multiple routes”You can also specify multiple paths for the same component.
@page "/people/{Id:int}"@page "/people/{Message}"@page "/people"<div>...</div>@code { [Parameter] public int? Id { get; set; } [Parameter] public string? Message { get; set; }}Navigation - Anchor
Section titled “Navigation - Anchor”To navigate between websites you can use the anchor element.
@page "/people"<div> ... <a href="/authors/1" class="...">Autoren</a></div>@code { ...}Navigation - Programmatically
Section titled “Navigation - Programmatically”To navigate programmatically, you can use the NavigationManager.
@page "/people"@inject NavigationManager _navManager<div>...</div>@code { public void Authorize(){ ... _navManager.NavigateTo("/authors/2", true); }}Navigation - Programmatically (2)
Section titled “Navigation - Programmatically (2)”@page "/people"@inject NavigationManager _navManager<div> <button @onclick="@( () => _navigationManager.NavigateTo( "/authors/2", true ) )"> Load Author </button></div>@code { ...}Dependency Injection
Section titled “Dependency Injection”To inject dependent types into Razor components, use the inject directive.
@page "/people"@inject NavigationManager _navManagerBinding
Section titled “Binding”There are 2 directions of data flow when working with values in Blazor:
- Binding the value of a variable to an element on the page, so that when the value of the variable changes, the updatet value gets shown on the page.
- Binding the value of an input element on the page to a variable, so that when the user enters a value on the page, the value of the variable gets updated.
Binding: variable to component
Section titled “Binding: variable to component”We already know how to achieve this, by simply using the Razor syntax to render the value of a variable.
<p>@message</p><input type="text" value="@message" />
@code { private string message = "Hello";}Whenever the value of the variable message changes, the changes will be reflected on the rendered page.
Binding: input element to variable
Section titled “Binding: input element to variable”There are 2 ways of achieving this:
- Change event handlers
- 2-way binding
Change event handlers
Section titled “Change event handlers”You can register an event handler to listen on changes of an input element.
<input type="text" @oninput="OnChange"/>
@code { private void OnChange(ChangeEventArgs obj) { var updatedValue = obj.Value as string; }}2-way binding
Section titled “2-way binding”You can combine the two binding variants to achieve a two-way binding, where an input element updates a variable and the other way round.
<input type="text" @oninput="OnChange" value="@message"></input>
@code { private string message = "Hello";
private void OnChange(ChangeEventArgs obj) { message = obj.Value as string ?? message; }}2-way binding (2)
Section titled “2-way binding (2)”Instead of wiring up the 2-way binding manually, you can use the predefined @bind-value directive, which does exactly that for you - show the value of the variable in HTML and use an event handler to update the variable in your code upon user inputs.
<input type="text" @bind-value="message"/>
@code { private string message = "Hello";}Forms are used to capture and process data, entered by users.
Using Razor Expressions you can bind objects directly to the values of the form. Use the bind-value attribute for that.
Forms - Class
Section titled “Forms - Class”public class Movie { [StringLength(100)] [Required] public string Title { get; set;} [StringLength(400)] [Required] public string Description { get; set; } ... public int Duration { get; set; } ... public EGenre Genre { get; set; }}Forms - Initialization
Section titled “Forms - Initialization”<EditForm Model="Movie" OnValidSubmit="Create" class="form"> <DataAnnotationsValidator/>...</EditForm>@code{ public Movie Movie { get; set; } = new (); public void Create() { ... }}Forms - Data Binding
Section titled “Forms - Data Binding”<EditForm ... class="form"> <DataAnnotationsValidator/> <div class="form-row"> <div class="form-group col-md-5"> <label for="movieTitle" class="small text-info">title:</label> <InputText class="form-control form-control-sm" id="movieTitle" placeholder="input title" @bind-Value="@Movie.Title"/> <ValidationMessage For="()=> Movie.Title"/> </div></div>...</EditForm>Forms - Send Request
Section titled “Forms - Send Request”<EditForm ... class="form"> ... <div class="form-row mt-3"> <NavLink href="movies" class="btn btn-danger btn-sm">Cancel</NavLink> <button class="btn btn-info ml-2 btn-sm">@ButtonLabel</button> </div></EditForm>