Blazor Component Created: 01 Feb 2026 Updated: 01 Feb 2026

Razor Syntax: The Bridge Between HTML and C#

Razor is a powerful markup syntax that allows developers to embed server-based code (C#) into web pages. Its greatest strength lies in its fluidity; unlike other languages that require heavy context switching, Razor allows you to weave C# logic directly into your HTML markup seamlessly. The Razor parser is smart enough to detect where the code ends and the HTML begins, leveraging your existing knowledge of both languages.

1. The @ Symbol: Starting the Transition

The magic character in Razor is @. It signals the transition from static HTML to dynamic C# code. This can be done through dedicated code blocks or inline expressions.

Razor Code Blocks

Code blocks allow you to write standard C# code within your .razor file. While the @code block is used for the component's main logic (properties, methods), you can also use inline blocks @{ ... } to execute logic directly within the render tree.

Example:

Instead of just rendering a name, let's create a dynamic message based on the time of day directly inside the HTML structure:

Razor CSHTML

@{
var hour = DateTime.Now.Hour;
string message = hour < 12 ? "Good Morning" : "Good Afternoon";
}

<div class="welcome-banner">
<h3>@message, User!</h3>
</div>

You can even define local functions inside these blocks to keep your markup clean:

@{
void RenderStatusBadge(bool isActive)
{
if (isActive)
{
<span class="badge bg-success">Online</span>
}
else
{
<span class="badge bg-danger">Offline</span>
}
}
}

<p>Server Status: @{ RenderStatusBadge(true); }</p>

2. Implicit Razor Expressions

Implicit expressions are the most common way to print values. You simply start with @ and access a property or variable. The parser identifies the end of the expression automatically (usually by a space or an HTML tag).

Example:

Displaying product details inside a card:

<div class="card">
<h1>@Product.Name</h1>
<p>Price: $@Product.Price</p>
</div>

Note: You cannot use generics (like List<string>) or spaces inside an implicit expression.

3. Explicit Razor Expressions

Sometimes, the Razor parser needs help understanding where the code stops, especially when doing calculations or when the code touches static text. Explicit expressions wrap the code in parentheses: @(...).

Example 1: Calculations

Instead of just printing a date, let's print the year 10 years from now:

<p>The warranty expires in: @(DateTime.Now.Year + 10)</p>

Example 2: Concatenation

If you want to attach a unit of measurement directly to a number without a space:

<span>Height: @(CurrentHeight)cm</span>

Example 3: Generics

To call a generic method, explicit expressions are mandatory to prevent the brackets < > from being confused with HTML tags:

<p>First Item: @(GetFirstItem<string>())</p>

4. Expression Encoding (HTML Safety)

By default, Razor protects you from Cross-Site Scripting (XSS) attacks. If a string contains HTML tags, Razor will encode them, displaying the tags as text rather than rendering them.

Example:

@("<h1>Critical Error!</h1>")

Browser Output: &lt;h1&gt;Critical Error!&lt;/h1&gt; (You will literally see the <h1> text).

To force the browser to render the string as actual HTML, you must cast it to MarkupString:

@((MarkupString)"<h1>Critical Error!</h1>")

Use this with caution and only with trusted data sources.

5. Directives: Controlling the Component

Directives are special keywords starting with @ that alter how the component is compiled or behaves.

DirectiveDescriptionCode-Behind Equivalent
@pageDefines the URL route for the component.N/A (Route attribute)
@usingImports a namespace (e.g., System.Text).using System.Text;
@injectInjects a service (DI).[Inject] private MyService Service {get; set;}
@layoutDefines a custom layout for the page.[Layout(typeof(MainLayout))]

Common Directive Examples

Routing with Parameters:

@page "/products/{productId:int}"

Implementing an Interface:

If your component needs to clean up resources, you implement IAsyncDisposable:

@implements IAsyncDisposable

@code {
public async ValueTask DisposeAsync()
{
// Cleanup logic here
}
}

Generic Components:

Creating a list component that can accept any type of item (TItem):

@typeparam TItem
<ul>
@foreach(var item in Items)
{
<li>@item.ToString()</li>
}
</ul>
@code {
[Parameter] public List<TItem> Items { get; set; }
}
Share this lesson: