ABS Razor Syntax
Razor is a markup syntax for embedding server-based code into web pages. The Razor syntax consists of Razor markup, C#, and HTML. Files containing Razor generally have a .cshtml file extension. Razor is also found in Razor components files (.razor).
Razor syntax
Razor supports C# and uses the @ symbol to transition from HTML to C#. Razor evaluates C# expressions and renders them in the HTML output.
When an @ symbol is followed by a Razor reserved keyword, it transitions into Razor-specific markup. Otherwise, it transitions into plain C#.
To escape an @ symbol in Razor markup, use a second @ symbol:
<p>@@Username</p>
The code is rendered in HTML with a single @ symbol:
<p>@Username</p>
HTML attributes and content containing email addresses don't treat the @ symbol as a transition character. The email addresses in the following example are untouched by Razor parsing:
<a href="mailto:Support@contoso.com">Support@contoso.com</a>
Implicit Razor expressions
Implicit Razor expressions start with @ followed by C# code:
<p>@DateTime.Now</p>
<p>@DateTime.IsLeapYear(2016)</p>
With the exception of the C# await keyword, implicit expressions must not contain spaces. If the C# statement has a clear ending, spaces can be intermingled:
<p>@await DoSomething("hello", "world")</p>
Implicit expressions cannot contain C# generics, as the characters inside the brackets (<>) are interpreted as an HTML tag. The following code is not valid:
<p>@GenericMethod<int>()</p>
The preceding code generates a compiler error similar to one of the following:
- The "int" element wasn't closed. All elements must be either self-closing or have a matching end-tag.
- Cannot convert method group 'GenericMethod' to non-delegate type 'object'. Did you intend to invoke the method?`
Generic method calls must be wrapped in an explicit Razor expression or a Razor code block.
Templated Razor delegates
Razor templates allow you to define a UI snippet with the following format:
Explicit Razor expressions
Explicit Razor expressions consist of an @ symbol with balanced parenthesis. To render last week's time, the following Razor markup is used:
<p>Last week this time: @(DateTime.Now - TimeSpan.FromDays(7))</p>
Any content within the @() parenthesis is evaluated and rendered to the output.
Implicit expressions, described in the previous section, generally can't contain spaces. In the following code, one week isn't subtracted from the current time:
<p>Last week: @DateTime.Now - TimeSpan.FromDays(7)</p>
The code renders the following HTML:
<p>Last week: 7/7/2016 4:39:52 PM - TimeSpan.FromDays(7)</p>
Explicit expressions can be used to concatenate text with an expression result:
@{
var joe = new Person("Joe", 33);
}
<p>Age@(joe.Age)</p>
Without the explicit expression, <p>Age@joe.Age</p>
is treated as an email address, and <p>Age@joe.Age</p>
is rendered. When written as an explicit expression,
Age33
is rendered.Explicit expressions can be used to render output from generic methods in .cshtml files. The following markup shows how to correct the error shown earlier caused by the brackets of a C# generic. The code is written as an explicit expression:
<p>@(GenericMethod<int>())</p>
Expression encoding
C# expressions that evaluate to a string are HTML encoded. C# expressions that evaluate to IHtmlContent are rendered directly through IHtmlContent.WriteTo. C# expressions that don't evaluate to IHtmlContent are converted to a string by ToString and encoded before they're rendered.
@("<span>Hello World</span>")
The preceding code renders the following HTML:
<span>Hello World</span>
The HTML is shown in the browser as plain text: Hello World
HtmlHelper.Raw
output isn't encoded but rendered as HTML markup.
Warning: Using HtmlHelper.Raw on unsanitized user input is a security risk. User input might contain malicious JavaScript or other exploits. Sanitizing user input is difficult. Avoid using HtmlHelper.Raw with user input.
@Html.Raw("<span>Hello World</span>")
The code renders the following HTML:
<span>Hello World</span>
Razor code blocks
Razor code blocks start with @ and are enclosed by {}. Unlike expressions, C# code inside code blocks isn't rendered. Code blocks and expressions in a view share the same scope and are defined in order:
@{
var quote = "The future depends on what you do today. - Mahatma Gandhi";
}
<p>@quote</p>
@{
quote = "Hate cannot drive out hate, only love can do that. - Martin Luther King, Jr.";
}
<p>@quote</p>
The code renders the following HTML:
<p>The future depends on what you do today. - Mahatma Gandhi</p>
<p>Hate cannot drive out hate, only love can do that. - Martin Luther King, Jr.</p>
In code blocks, declare local functions with markup to serve as templating methods:
@{
void RenderName(string name)
{
<p>Name: <strong>@name</strong></p>
}
RenderName("Mahatma Gandhi");
RenderName("Martin Luther King, Jr.");
}
The code renders the following HTML:
<p>Name: <strong>Mahatma Gandhi</strong></p>
<p>Name: <strong>Martin Luther King, Jr.</strong></p>
Implicit transitions
The default language in a code block is C#, but the Razor Page can transition back to HTML:
@{
var inCSharp = true;
<p>Now in HTML, was in C# @inCSharp</p>
}
Explicit delimited transition
To define a subsection of a code block that should render HTML, surround the characters for rendering with the Razor
@for (var i = 0; i < people.Length; i++)
{
var person = people[i];
<text>Name: @person.Name</text>
}
Use this approach to render HTML that isn't surrounded by an HTML tag. Without an HTML or Razor tag, a Razor runtime error occurs.
The <text>
tag is useful to control whitespace when rendering content:
- Only the content between the
tag is rendered. - No whitespace before or after the
tag appears in the HTML output.
Explicit line transition
To render the rest of an entire line as HTML inside a code block, use @: syntax:
@for (var i = 0; i < people.Length; i++)
{
var person = people[i];
@:Name: @person.Name
}
Without the @:
in the code, a Razor runtime error is generated.
Extra @
characters in a Razor file can cause compiler errors at statements later in the block. These compiler errors can be difficult to understand because the actual error occurs before the reported error. This error is common after combining multiple implicit/explicit expressions into a single code block.
Control structures
Control structures are an extension of code blocks. All aspects of code blocks (transitioning to markup, inline C#) also apply to the following structures:
Conditionals @if, else if, else, and @switch
@if
controls when code runs:
@if (value % 2 == 0)
{
<p>The value was even.</p>
}
else
and else if
don't require the @ symbol:
@if (value % 2 == 0)
{
<p>The value was even.</p>
}
else if (value >= 1337)
{
<p>The value is large.</p>
}
else
{
<p>The value is odd and small.</p>
}
The following markup shows how to use a switch statement:
@switch (value)
{
case 1:
<p>The value is 1!</p>
break;
case 1337:
<p>Your number is 1337!</p>
break;
default:
<p>Your number wasn't 1 or 1337.</p>
break;
}
Looping @for, @foreach, @while, and @do while
Templated HTML can be rendered with looping control statements. To render a list of people:
@{
var people = new AccountHolder[]
{
new AccountHolder(){...},
new AccountHolder(){...},
...
};
}
The following looping statements are supported:
@for
@for (var i = 0; i < people.Length; i++)
{
var person = people[i];
<p>Name: @person.Name</p>
<p>Age: @person.Age</p>
}
@foreach
@foreach (var person in people)
{
<p>Name: @person.Name</p>
<p>Age: @person.Age</p>
}
@while
@{ var i = 0; }
@while (i < people.Length)
{
var person = people[i];
<p>Name: @person.Name</p>
<p>Age: @person.Age</p>
i++;
}
@do while
@{ var i = 0; }
@do
{
var person = people[i];
<p>Name: @person.Name</p>
<p>Age: @person.Age</p>
i++;
} while (i < people.Length);
Compound @using
In C#, a using statement is used to ensure an object is disposed. In Razor, the same mechanism is used to create HTML Helpers that contain additional content. In the following code, HTML Helpers render a