"
 
 
 
ASP.NET (snapshot 2017) Microsoft documentation and samples

Razor syntax for ASP.NET Core

By Rick Anderson, Luke Latham, Taylor Mullen, and Dan Vicarel

Razor is a markup syntax for embedding server-based code into webpages. The Razor syntax consists of Razor markup, C#, and HTML. Files containing Razor generally have a .cshtml file extension.

Rendering HTML

The default Razor language is HTML. Rendering HTML from Razor markup is no different than rendering HTML from an HTML file. HTML markup in .cshtml Razor files is rendered by the server unchanged.

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:

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:[email protected]">[email protected]</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:

Generic method calls must be wrapped in an explicit Razor expression or a Razor code block. This restriction doesn’t apply to .vbhtml Razor files because Visual Basic syntax places parentheses around generic type parameters instead of brackets.

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:

[!code-cshtmlMain]

   1:  <!-- Single statement blocks.  -->
   2:  @{ var total = 7; }
   3:   
   4:  <!-- Multi-statement block.  -->
   5:  @{
   6:      var greeting = "Welcome!";
   7:      var weekDay = DateTime.Now.DayOfWeek;
   8:      var leapYear = DateTime.IsLeapYear(DateTime.Now.Year);
   9:      var greetingMessage = greeting + " Today is: " + weekDay
  10:          + " -Leap year: " + leapYear;
  11:   
  12:      <p>The greeting is :<br /> @greetingMessage</p>
  13:      <p>The value of your account is: @total </p>
  14:  }
  15:  @* End of greeting *@
  16:   
  17:  <p>Last week: @DateTime.Now - TimeSpan.FromDays(7)</p>
  18:   
  19:  @*Add () to get correct time.*@
  20:  <p>Last week: @(DateTime.Now - TimeSpan.FromDays(7))</p>
  21:  @*End of correct time*@
  22:   
  23:  <a href="mailto:Support@contoso.com">Support@contoso.com</a>
  24:   
  25:  <br /><br /> 
  26:   
  27:  @("<span>Hello World</span>")
  28:   
  29:  <br /><br />
  30:   
  31:  @Html.Raw("<span>Hello World</span>")
  32:   
  33:  <br /><br />
  34:   
  35:  <!-- Embedding a backslash in a string -->
  36:  @{ var myFilePath = @"C:\MyFolder\"; }
  37:  <p>The path is: @myFilePath</p>
  38:   
  39:   
  40:  <br /><br />
  41:   
  42:  <!-- Embedding double quotation marks in a string -->
  43:  @{ var myQuote = @"The person said: ""Hello, today is Monday."""; }
  44:  <p>@myQuote</p>
  45:   
  46:  @{
  47:      var inCSharp = true;
  48:      <p>Now in HTML, was in C# @inCSharp</p>
  49:  }
  50:   
  51:  @{
  52:  /* C# */<text>I'm HTML</text>            /* C# */
  53:  }
  54:   
  55:  <br /><br />
  56:   
  57:  @{
  58:  /* Still C# */@: <p>Hello World</p> /* This is not C#, it's HTML */
  59:  }
  60:   
  61:   
  62:  <br /><br />
  63:  @{
  64:  /* Still C# */<text> <p>Hello World</p> /* This is not C#, it's HTML */</text>
  65:  }
  66:   
  67:   
  68:   
  69:   
  70:  @{ var @value = 77; }
  71:   
  72:  @if (value % 2 == 0)
  73:  {
  74:      <p>The value was even</p>
  75:  }
  76:  else if (value >= 1337)
  77:  {
  78:      <p>The value is large.</p>
  79:  }
  80:  else
  81:  {
  82:      <p>The value was not large and is odd.</p>
  83:  }
  84:   
  85:  <br /><br />
  86:   
  87:  @switch (value)
  88:  {
  89:      case 1:
  90:          <p>The value is 1!</p>
  91:          break;
  92:      case 1337:
  93:          <p>Your number is 1337!</p>
  94:          break;
  95:      default:
  96:          <p>Your number was not 1 or 1337.</p>
  97:          break;
  98:  }
  99:  @*  *@
 100:    @try
 101:    {
 102:        throw new InvalidOperationException("You did something invalid.");
 103:    }
 104:    catch (Exception ex)
 105:    {
 106:        <p>The exception message: @ex.Message</p>
 107:    }
 108:    finally
 109:    {
 110:        // Do something.
 111:    }
 112:   
 113:  <br /><br />
 114:   
 115:    @{
 116:        /* C# comment. */
 117:        // Another C# comment.
 118:    }
 119:    <!-- HTML comment -->
 120:   
 121:      @*
 122:      @{
 123:          /* C# comment. */
 124:          // Another C# comment.
 125:      }
 126:      <!-- HTML comment -->
 127:     *@
 128:   
 129:    <!-- HTML comment 2 -->
 130:   
 131:   
 132:   
 133:  <!-- Single statement blocks.  -->
 134:   
 135:  <!-- Multi-statement block.  -->
 136:      <p>The greeting is :<br /> Welcome! Today is: Tuesday -Leap year: True</p>
 137:      <p>The value of your account is: 7 </p>
 138:      <p>The value of myMessage is: Hello World</p>

The code renders the following HTML:

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>[email protected]</p> is treated as an email address, and <p>[email protected]</p> is rendered. When written as an explicit expression, <p>Age33</p> is rendered.

Explicit expressions can be used to render output from generic methods in .cshtml files. In an implicit expression, the characters inside the brackets (<>) are interpreted as an HTML tag. The following markup is not valid Razor:

<p>@GenericMethod<int>()</p>

The preceding code generates a compiler error similar to one of the following:

The following markup shows the correct way write this code. The code is written as an explicit expression:

<p>@(GenericMethod<int>())</p>

Note: this restriction doesn’t apply to .vbhtml Razor files. With .vbhtml Razor files, Visual Basic syntax places parentheses around generic type parameters instead of brackets.

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 code renders the following HTML:

The HTML is shown in the browser as:

<span>Hello World</span>

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:

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:

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 <text> tag:

@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:

Explicit Line Transition with @:

To render the rest of an entire line as HTML inside a code block, use the @: 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.

Warning: Extra @ characters in a Razor file can cause 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 Person[]
    {
          new Person("Weston", 33),
          new Person("Johnathon", 41),
          ...
    };
}

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 form tag with the @using statement:

@using (Html.BeginForm())
{
    <div>
        email:
        <input type="email" id="Email" value="">
        <button>Register</button>
    </div>
}

Scope-level actions can be performed with (xref:)Tag Helpers.

@try, catch, finally

Exception handling is similar to C#:

[!code-cshtmlMain]

   1:  @try
   2:  {
   3:      throw new InvalidOperationException("You did something invalid.");
   4:  }
   5:  catch (Exception ex)
   6:  {
   7:      <p>The exception message: @ex.Message</p>
   8:  }
   9:  finally
  10:  {
  11:      <p>The finally statement.</p>
  12:  }

@lock

Razor has the capability to protect critical sections with lock statements:

@lock (SomeLock)
{
    // Do critical section work
}

Comments

Razor supports C# and HTML comments:

@{
    /* C# comment */
    // Another C# comment
}
<!-- HTML comment -->

The code renders the following HTML:

Razor comments are removed by the server before the webpage is rendered. Razor uses @* *@ to delimit comments. The following code is commented out, so the server doesn’t render any markup:

@*
    @{
        /* C# comment */
        // Another C# comment
    }
    <!-- HTML comment -->
*@

Directives

Razor directives are represented by implicit expressions with reserved keywords following the @ symbol. A directive typically changes the way a view is parsed or enables different functionality.

Understanding how Razor generates code for a view makes it easier to understand how directives work.

[!code-htmlMain]

   1:  @{
   2:      var quote = "Getting old ain't for wimps! - Anonymous";
   3:  }
   4:   
   5:  <div>Quote of the Day: @quote</div>

The code generates a class similar to the following:

Later in this article, the section Viewing the Razor C# class generated for a view explains how to view this generated class.

@using

The @using directive adds the C# using directive to the generated view:

[!code-cshtmlMain]

   1:  @using System.IO
   2:  @{
   3:      var dir = Directory.GetCurrentDirectory();
   4:  }
   5:  <p>@dir</p>

@model

The @model directive specifies the type of the model passed to a view:

@model TypeNameOfModel

In an ASP.NET Core MVC app created with individual user accounts, the Views/Account/Login.cshtml view contains the following model declaration:

@model LoginViewModel

The class generated inherits from RazorPage<dynamic>:

Razor exposes a Model property for accessing the model passed to the view:

<div>The Login Email: @Model.Email</div>

The @model directive specifies the type of this property. The directive specifies the T in RazorPage<T> that the generated class that the view derives from. If the @model directive iisn’t specified, the Model property is of type dynamic. The value of the model is passed from the controller to the view. For more information, see [Strongly typed models and the @model keyword.

@inherits

The @inherits directive provides full control of the class the view inherits:

@inherits TypeNameOfClassToInheritFrom

The following code is a custom Razor page type:

[!code-csharpMain]

   1:  using Microsoft.AspNetCore.Mvc.Razor;
   2:   
   3:  public abstract class CustomRazorPage<TModel> : RazorPage<TModel>
   4:  {
   5:      public string CustomText { get; } = "Gardyloo! - A Scottish warning yelled from a window before dumping a slop bucket on the street below.";
   6:  }

The CustomText is displayed in a view:

[!code-cshtmlMain]

   1:  @inherits CustomRazorPage<TModel>
   2:   
   3:  <div>Custom text: @CustomText</div>

The code renders the following HTML:

@model and @inherits can be used in the same view. @inherits can be in a *_ViewImports.cshtml* file that the view imports:

[!code-cshtmlMain]

   1:  @inherits CustomRazorPage<TModel>

The following code is an example of a strongly-typed view:

[!code-cshtmlMain]

   1:  @inherits CustomRazorPage<TModel>
   2:   
   3:  <div>The Login Email: @Model.Email</div>
   4:  <div>Custom text: @CustomText</div>

If “[email protected]” is passed in the model, the view generates the following HTML markup:

@inject

The @inject directive enables the Razor Page to inject a service from the (xref:)service container into a view. For more information, see (xref:)Dependency injection into views.

@functions

The @functions directive enables a Razor Page to add function-level content to a view:

@functions { // C# Code }

For example:

[!code-cshtmlMain]

   1:  @functions {
   2:      public string GetHello()
   3:      {
   4:          return "Hello";
   5:      }
   6:  }
   7:   
   8:  <div>From method: @GetHello()</div> 

The code generates the following HTML markup:

The following code is the generated Razor C# class:

[!code-csharpMain]

   1:  using System.Threading.Tasks;
   2:  using Microsoft.AspNetCore.Mvc.Razor;
   3:   
   4:  public class _Views_Home_Test_cshtml : RazorPage<dynamic>
   5:  {
   6:      // Functions placed between here 
   7:      public string GetHello()
   8:      {
   9:          return "Hello";
  10:      }
  11:      // And here.
  12:  #pragma warning disable 1998
  13:      public override async Task ExecuteAsync()
  14:      {
  15:          WriteLiteral("\r\n<div>From method: ");
  16:          Write(GetHello());
  17:          WriteLiteral("</div>\r\n");
  18:      }
  19:  #pragma warning restore 1998
  20:  }
  21:   
  22:   
  23:   
  24:  /*
  25:   * #pragma checksum "/Views/Home/Contact5.cshtml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "df105f5597cff871aaa18b2a5cc82662d6e6963d"
  26:  namespace AspNetCore
  27:  {
  28:  #line 1 "/Views/_ViewImports.cshtml"
  29:  using RazorSample
  30:  
  31:  #line default
  32:  #line hidden
  33:  ;
  34:  using System;
  35:  using System.Linq;
  36:  using System.Collections.Generic;
  37:  using Microsoft.AspNetCore.Mvc;
  38:  using Microsoft.AspNetCore.Mvc.Rendering;
  39:  using Microsoft.AspNetCore.Mvc.ViewFeatures;
  40:  using System.Threading.Tasks;
  41:  
  42:  public class _Views_Home_Contact5_cshtml : Microsoft.AspNetCore.Mvc.Razor.RazorPage<dynamic>
  43:  {
  44:  #line 1 "/Views/Home/Contact5.cshtml"
  45:  
  46:  public string GetHello()
  47:  {
  48:      return "Hello";
  49:  }
  50:  
  51:  #line default
  52:  #line hidden
  53:      #line hidden
  54:      public _Views_Home_Contact5_cshtml()
  55:      {
  56:      }
  57:      #line hidden
  58:      [Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
  59:      public Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider ModelExpressionProvider { get; private set; }
  60:      [Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
  61:      public Microsoft.AspNetCore.Mvc.IUrlHelper Url { get; private set; }
  62:      [Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
  63:      public Microsoft.AspNetCore.Mvc.IViewComponentHelper Component { get; private set; }
  64:      [Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
  65:      public Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper Json { get; private set; }
  66:      [Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
  67:      public Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper<dynamic> Html { get; private set; }
  68:  
  69:      #line hidden
  70:  
  71:      #pragma warning disable 1998
  72:      public override async Task ExecuteAsync()
  73:      {
  74:          BeginContext(86, 20, true);
  75:          WriteLiteral("\r\n<div>From method: ");
  76:          EndContext();
  77:          BeginContext(107, 10, false);
  78:  #line 8 "/Views/Home/Contact5.cshtml"
  79:           Write(GetHello());
  80:  
  81:  #line default
  82:  #line hidden
  83:          EndContext();
  84:          BeginContext(117, 8, true);
  85:          WriteLiteral("</div>\r\n");
  86:          EndContext();
  87:      }
  88:      #pragma warning restore 1998
  89:  }
  90:  }
  91:  */

@section

The @section directive is used in conjunction with the (xref:)layout to enable views to render content in different parts of the HTML page. For more information, see (xref:)Sections.

Tag Helpers

There are three directives that pertain to (xref:)Tag Helpers.

Directive Function
[@addTagHelper](xref:mvc/views/tag-helpers/intro#add-helper-label) Makes Tag Helpers available to a view.
[@removeTagHelper](xref:mvc/views/tag-helpers/intro#remove-razor-directives-label) Removes Tag Helpers previously added from a view.
[@tagHelperPrefix](xref:mvc/views/tag-helpers/intro#prefix-razor-directives-label) Specifies a tag prefix to enable Tag Helper support and to make Tag Helper usage explicit.

Razor reserved keywords

Razor keywords

Razor keywords are escaped with @(Razor Keyword) (for example, @(functions)).

C# Razor keywords

C# Razor keywords must be double-escaped with @(@C# Razor Keyword) (for example, @(@case)). The first @ escapes the Razor parser. The second @ escapes the C# parser.

Reserved keywords not used by Razor

Viewing the Razor C# class generated for a view

Add the following class to the ASP.NET Core MVC project:

[!code-csharpMain]

   1:  using Microsoft.AspNetCore.Mvc.Razor.Extensions;
   2:  using Microsoft.AspNetCore.Razor.Language;
   3:   
   4:  public class CustomTemplateEngine : MvcRazorTemplateEngine
   5:  {
   6:      public CustomTemplateEngine(RazorEngine engine, RazorProject project) 
   7:          : base(engine, project)
   8:      {
   9:      }
  10:          
  11:      public override RazorCSharpDocument GenerateCode(RazorCodeDocument codeDocument)
  12:      {
  13:          var csharpDocument = base.GenerateCode(codeDocument);
  14:          var generatedCode = csharpDocument.GeneratedCode;
  15:   
  16:          // Look at generatedCode
  17:   
  18:          return csharpDocument;
  19:      }
  20:  }

Override the RazorTemplateEngine added by MVC with the CustomTemplateEngine class:

[!code-csharpMain]

   1:  using Microsoft.AspNetCore.Builder;
   2:  using Microsoft.AspNetCore.Hosting;
   3:  using Microsoft.Extensions.DependencyInjection;
   4:  using Microsoft.AspNetCore.Razor.Language;
   5:   
   6:  namespace RazorSample
   7:  {
   8:      public class Startup
   9:      {
  10:          public void ConfigureServices(IServiceCollection services)
  11:          {
  12:              services.AddMvc();
  13:              services.AddSingleton<RazorTemplateEngine, CustomTemplateEngine>();
  14:          }
  15:   
  16:          public void Configure(IApplicationBuilder app, IHostingEnvironment env)
  17:          {
  18:              if (env.IsDevelopment())
  19:              {
  20:                  app.UseDeveloperExceptionPage();
  21:              }
  22:              else
  23:              {
  24:                  app.UseExceptionHandler("/Home/Error");
  25:              }
  26:   
  27:              app.UseStaticFiles();
  28:              app.UseMvcWithDefaultRoute();
  29:          }
  30:      }
  31:  }

Set a break point on the return csharpDocument statement of CustomTemplateEngine. When program execution stops at the break point, view the value of generatedCode.

Text Visualizer view of generatedCode
Text Visualizer view of generatedCode

View lookups and case sensitivity

The Razor view engine performs case-sensitive lookups for views. However, the actual lookup is determined by the underlying file system:

Developers are encouraged to match the casing of file and directory names to the casing of:

* Area, controller, and action names. 
* Razor Pages.

Matching case ensures the deployments find their views regardless of the underlying file system.





Comments ( )
<00>  <01>  <02>  <03>  <04>  <05>  <06>  <07>  <08>  <09>  <10>  <11>  <12>  <13>  <14>  <15>  <16>  <17>  <18>  <19>  <20>  <21>  <22>  <23
Link to this page: //www.vb-net.com/AspNet-DocAndSamples-2017/aspnetcore/mvc/views/razor.htm
<SITEMAP>  <MVC>  <ASP>  <NET>  <DATA>  <KIOSK>  <FLEX>  <SQL>  <NOTES>  <LINUX>  <MONO>  <FREEWARE>  <DOCS>  <ENG>  <CHAT ME>  <ABOUT ME>  < THANKS ME>