Learning how to write Razor syntax
Razor syntax is a combination of HTML, Razor markup, and C#. The syntax is similar to other JavaScript SPA frameworks, such as Vue.js, React, and Angular. The HTML in the Razor component is rendered the same way as it is in the HTML file. In the Razor component, you can fluently move between HTML markup and C# code.
Razor uses the @
symbol to determine the Razor syntax. If the @
symbol is followed by a reserved keyword, then the code is transitioned to Razor syntax. This Razor syntax can add dynamic logic to our components. The expressions can be implicit, explicit, inline, or in the form of code blocks.
Writing implicit Razor expressions
Implicit Razor expressions start with the @
symbol, followed by C# code:
<span>It is @DateTime.Now</span>
In the preceding code, @
is followed by the C# code directly. Implicit Razor expressions can’t contain spaces or generic calls, because <
and >
symbols in the generic call are translated as HTML in the Razor syntax. The only exception is the await
keyword, which can be followed by a space. If the method is used in the implicit Razor syntax call, the spaces can be used in the arguments.
Writing explicit Razor expressions
Explicit Razor expressions start with @
, followed by parentheses:
<span>It was @(DateTime.Now – TimeSpan.FromDays(7))</span>
The preceding code renders the date in the last week. Explicit Razor expressions are used when we can’t access the result value directly in the property or field or when we need to calculate some result, use generic calls, or prevent the value in the HTML string from being concatenated. Here is an example:
@{ var addr = new Address(Street: "Fairmont St NW", City: "Washington", "PostalCode": "20009"); } <span>The address is@addr.Street @addr.City @addr.PostalCode</span>
The preceding code will render the following output HTML:
<span>The address is@addr.Street Washington 20009</span>
In the preceding output, addr.Street
is not replaced by the property value because the term may comprise the syntax of an email address – that is, is@addr.Street
. When we need to use a directive just after a letter, we need to use the explicit Razor syntax:
<span>The address is@(addr.Street) @addr.City @addr.PostalCode</span>
As expected, the preceding code will generate the output HTML:
<span>The address isFairmont St NW Washington 20009</span>
Important information
If the @
symbol follows the letter, it is not translated to the Razor directive. If you need to render @
in the HTML, you can escape the symbol with another @
.
For example, @@MyUserName
will render in the HTML as @MyUserName
.
Writing inline expressions
Inline expressions are all of the expressions on a single line. Both implicit and explicit expressions are inline expressions.
Writing code block expressions
When creating our Razor components, we need to use some functionality other than just the properties or fields from C#. The code block expressions start with the @
symbol and are enclosed within curly brackets:
@{ var title = "About Blazor WebAssembly"; } <h2>@title</h2> @{ title = "Razor syntax"; } <h2>@title</h2>
The preceding code will generate the following output HTML:
<h2>About Blazor WebAssembly</h2> <h2>Razor syntax</h2>
As you can see in the preceding output, the generated HTML consists of two headlines.
Block expressions can also be used to create local functions to render repeated HTML code:
@{ void RenderTitle(string title) { <h2>@title</h2> } RenderTitle("About Blazor WebAssembly"); RenderTitle("Razor syntax"); }
The output HTML generated from the preceding code will be the same as in the first example in this section. We do not need to modify the variable each time we want to render the title because we can use the RenderTitle
function defined in the code block. This example shows simple code, but in the real world, the local function will contain more complex code.
Writing control structures
Control structures are specific types of code blocks. They are used when the code block has some specific meaning to the code, such as conditions, loops, and so on.
Conditions
We can use the if
directive to start a code block with conditions:
@if (chapterNumber == 1) { <p>This is the first chapter.</p> } else if (chapterNumber == 6) { <p>This is the last chapter.</p> } else { <p>Chapter @chapterNumber</p> }
The preceding code shows a full if - else if – else
statement for rendering paragraph information for each chapter in this book. The same condition can be applied by the switch
statement:
@switch (chapterNumber) { case 1: <p>This is the first chapter.</p> break; case 6: <p>This is the last chapter.</p> break; default: <p>Chapter @chapterNumber</p> break; }
The preceding switch
statement will generate the same HTML result as the if
statement.
Loops
The following loop types are supported in Razor syntax:
for
foreach
while
do while
Each loop starts with the @
symbol. Looping through a collection of items helps you in situations where you want to apply some repetitive code to each item in the collection. The following example shows the looping of chapters
:
@{ var chapters = new Chapter[] { new Chapter(1, "Learning Razor syntax"), new Chapter(2, "Creating Razor components"), new Chapter(3, "Understanding page routing in Blazor"), … }; }
The preceding code defines a new chapters
variable that will be used in the following loop examples:
- The following is an example of a
for
loop:@for (var i = 0; i < chapters.Length; i++) { var chapter = chapters[i]; <h2>Chapter no. @chapter.Number: @chapter.Title</h2> }
- The following is an example of a
foreach
loop:@foreach (var chapter in chapters) { <h2>Chapter no. @chapter.Number: @chapter.Title</h2> }
- The following is an example of a
while
loop:@{ var i = 0; } @while (i < chapters.Length) { var chapter = chapters[i]; <h2>Chapter no. @chapter.Number: @chapter.Title</h2> i++; }
- The following is an example of a
do while
loop:@{ var i = 0; } @do { var chapter = chapters[i]; <h2>Chapter no. @chapter.Number: @chapter.Title</h2> i++; } while (i < chapters.Length)
As you can see, the Razor syntax is similar to the C# syntax. The only difference is in the transition between C# code and HTML code.
Razor syntax allows some other keywords to be used in the code blocks, such as @using
(for disposable objects), @try
, catch
, finally
, and @lock
. The HTML and C# comments are also allowed.
Writing top-level directives
Razor directives, which are at the top of the file, control many aspects of the component. They can change the way the component is compiled, how the component is used on the website, or who can view the component’s output. The directives should be at the top of the file, but the order of the directives is not defined. Here is the list of these top-level directives:
@page
: This directive specifies the page where the component is rendered. We will learn more about this in the following sections. Here is an example of the directive for the home page:@page "/home"
@namespace
: The@namespace
directive can override the namespace for the component. The default component namespace is based on the folder structure. Here is an example of namespace overriding:@namespace DemoProject.MyLibrary.Components
@inherits
: When we want to change the base class of the component, we need to use the@inherits
directive, as shown in the following example:@inherits CustomComponentBase
@implements
: Our component can implement any interface. This directive can be used multiple times. Here is an example of implementing two interfaces:@implements IDisposable @implements ISortable
@layout
: The@layout
directive is only used on the component that contains the@page
directive. The default layout is used if nothing has been set. If the page directive is missing, the@layout
directive is ignored. Here is an example of the layout directive setting the layout toLoginLayout
:@layout LoginLayout
@attribute
: The@attribute
directive adds a class-level attribute to the component class. This directive can be used multiple times. Here is an example of marking a component for only authorized viewing:@attribute [Authorize]
@using
: This directive can be used multiple times to import namespaces to the component scope:@using DemoProject.Model
@typeparam
: The@typeparam
directive is mostly used in combination with the generic base class in the@inherits
directive. If the base class contains multiple generic types, the order of the@typeparam
directive must reflect the order of the generic types:@implements MyBaseClass<TItemModel, TFilterModel> @typeparam MyItemModel @typeparam MyFilterModel
@inject
: The@inject
directive injects service from the dependency injection container into the component:@inject HttpClient Client @inject IJSRuntime JS
The preceding code shows how to inject an HttpClient
into the Client
property and IJSRuntime
into the JS
property.
Writing inline directives
Inline directives are used in the HTML or Razor components. These directives include the following:
@attributes
: These directives represent a collection (Dictionary<string, object>
) of HTML attributes that we want to render in the child component that has not specified these HTML attributes as component parameter properties:@{ Dictionary<string, object> AdditionalAttributes = new Dictionary<string, object() { { "tooltip", "Set your full name." }, { "required", "true" }, { "data-id", 150 } }; } <input @attributes="AdditionalAttributes" />
@bind
: This directive creates two-way data binding for a component with user input:@{ public string UserName { get; set; } } <input type="text" @bind-Value="UserName" />
@on{event}
: This directive adds an event handler for the event specified (click
,change
, and so on):<button @onclick="OnClickHandler">Click here!</button>
@key
: This directive specifies the unique key used to render the collection of data in loops (for
,foreach
,while
, anddo while
):@for (var i = 1; i <= 10; i++) { <p @key="i">This is row @i</p> }
Such keys are used when updating the rendered data to update a correct item of the loop, instead of updating the whole loop.
@ref
: This directive captures a reference to the component or HTML element:<ConfirmBox @ref="myConfirmBox" /> @code { … myConfirmBox.OnConfirm(…); … }
@ref
can be used to trigger JavaScript events.
Now that we know how to write Razor syntax, let’s learn how to use Razor syntax and create fully functional Razor components.