Razor Справочник по синтаксису для ASP.NET Core

Рик Андерсон, Тейлор Маллен и Дэн Викарель

Razor — это синтаксис разметки для внедрения кода на основе .NET на веб-страницы. Синтаксис Razor состоит из разметки Razor , C#и HTML. Файлы, Razor содержащие обычно .cshtml расширение файла. Razor также находится в Razor файлах компонентов (.razor). Razor синтаксис аналогичен обработчикам шаблонов различных платформ одностраничных приложений JavaScript (SPA), таких как Angular, React, VueJs и Svelte. Дополнительные сведения см. в статье об устаревших функциях по состоянию на ASP.NET Core 3.0.

Введение в ASP.NET веб-программирование с помощью синтаксиса Razor предоставляет множество примеров программирования с синтаксисомRazor. Хотя этот раздел написан для ASP.NET, а не для ASP.NET Core, большинство примеров применяются к ASP.NET Core.

Отрисовка HTML

Язык по умолчанию Razor — HTML. Отрисовка HTML из Razor разметки отличается от отрисовки HTML-файла. Разметка HTML в .cshtmlRazor файлах отрисовывается сервером без изменений.

Синтаксис Razor

Razor поддерживает C# и использует @ символ для перехода с HTML на C#. Razor вычисляет выражения C# и отрисовывает их в выходных данных HTML.

Если за символом следует зарезервированная @Razor ключевое слово, он переходит в Razorразметку с определенной разметкой. В противном случае он переходит в обычный HTML-код.

Чтобы избежать символа @ в Razor разметке, используйте второй @ символ:

<p>@@Username</p>

Код будет отображен в HTML с одним символом @:

<p>@Username</p>

HTML-атрибуты и содержимое, включающие адреса электронной почты, не расценивают символ @ как символ перехода. Адреса электронной почты в следующем примере не касаются Razor синтаксического анализа:

<a href="mailto:Support@contoso.com">Support@contoso.com</a>

Масштабируемая векторная графика (SVG)

Поддерживаются элементы SVGforeignObject :

@{
    string message = "foreignObject example with Scalable Vector Graphics (SVG)";
}

<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg">
    <rect x="0" y="0" rx="10" ry="10" width="200" height="200" stroke="black" 
        fill="none" />
    <foreignObject x="20" y="20" width="160" height="160">
        <p>@message</p>
    </foreignObject>
</svg>

Неявные Razor выражения

Неявные Razor выражения начинаются с @ кода C#:

<p>@DateTime.Now</p>
<p>@DateTime.IsLeapYear(2016)</p>

Неявные выражения не должны содержать пробелов. Исключением является ключевое слово C# await. Если оператор C# имеет четкое окончание, пробелы вставлять можно:

<p>@await DoSomething("hello", "world")</p>

Неявные выражения не могут содержать универсальные шаблоны C#, так как символы в угловых скобках (<>) интерпретируются как тег HTML. Следующий код является недопустимым:

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

Приведенный выше код вызывает ошибку компилятора примерно следующего вида:

  • Элемент "int" не был закрыт. Все элементы должны быть самозакрывающимися или иметь соответствующий закрывающий тег.
  • Не удается преобразовать группу методов "GenericMethod" в не являющийся делегатом тип "object". Предполагалось вызывать этот метод?

Вызовы универсальных методов должны быть упакованы в явное Razor выражение или Razor блок кода.

Явные Razor выражения

Явные Razor выражения состоят из символа с сбалансированной @ скобкой. Для отображения времени прошлой недели используется следующая Razor разметка:

<p>Last week this time: @(DateTime.Now - TimeSpan.FromDays(7))</p>

Любое содержимое в скобках @() вычисляется и отображается в выходных данных.

Неявные выражения, описанные в предыдущем разделе, обычно не содержат пробелов. В следующем коде из значения текущего времени неделя не вычитается:

<p>Last week: @DateTime.Now - TimeSpan.FromDays(7)</p>

Код отображает следующий HTML:

<p>Last week: 7/7/2016 4:39:52 PM - TimeSpan.FromDays(7)</p>

Явные выражения позволяют объединять результат своего выполнения с дополнительным текстом:

@{
    var joe = new Person("Joe", 33);
}

<p>Age@(joe.Age)</p>

Без явного выражения <p>Age@joe.Age</p> обрабатывается как адрес электронной почты, и на выходе отображается <p>Age@joe.Age</p>. Если же текст написан как явное выражение, то вы получите <p>Age33</p>.

Явные выражения можно использовать для отображения выходных данных из универсальных методов в .cshtml файлах. В следующем примере показано, как исправить ошибку, показанную ранее и вызванную скобками в универсальном шаблоне C#. Код записывается как явное выражение:

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

Кодирование выражений

Выражения C#, которые имеют строковое выходное значение, кодируются в формате HTML. Выражения C#, которые имеют значение IHtmlContent, обрабатываются непосредственно с помощью IHtmlContent.WriteTo. Выражения C#, которые не имеют выходное значение IHtmlContent, преобразуются в строку с помощью ToString и кодируются перед обработкой.

@("<span>Hello World</span>")

Приведенный выше код отображает следующий HTML-код:

&lt;span&gt;Hello World&lt;/span&gt;

HTML-код отображается в браузере в виде обычного текста:

<span>Hello World</span>

Выходные данные HtmlHelper.Raw не кодируются, но отображаются в виде разметки HTML.

Предупреждение

Использование HtmlHelper.Raw с непроверенными входными данными пользователя представляет угрозу безопасности. Эти входные данные могут содержать вредоносный код JavaScript или другие эксплойты. Очистка вводимых пользователем данных является сложной задачей. Старайтесь не использовать HtmlHelper.Raw с такими данными.

@Html.Raw("<span>Hello World</span>")

Код отображает следующий HTML:

<span>Hello World</span>

Razor Блоки кода

Razor Блоки кода начинаются с @ и заключены в {}них. В отличие от выражений код C# внутри блоков кода не обрабатывается. Блоки кода и выражения в представлении используют общую область и определяются в следующем порядке:

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

Код отображает следующий 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>

В блоках кода объявите локальные функции с помощью разметки для использования в качестве методов создания шаблонов:

@{
    void RenderName(string name)
    {
        <p>Name: <strong>@name</strong></p>
    }

    RenderName("Mahatma Gandhi");
    RenderName("Martin Luther King, Jr.");
}

Код отображает следующий HTML:

<p>Name: <strong>Mahatma Gandhi</strong></p>
<p>Name: <strong>Martin Luther King, Jr.</strong></p>

Неявные переходы

Язык по умолчанию в блоке кода — C#, но Razor страница может вернуться к HTML:

@{
    var inCSharp = true;
    <p>Now in HTML, was in C# @inCSharp</p>
}

Явный переход с разделителями

Чтобы определить подраздел блока кода, который должен отображать HTML, окружает символы для отрисовки с тегом Razor<text> :

@for (var i = 0; i < people.Length; i++)
{
    var person = people[i];
    <text>Name: @person.Name</text>
}

Используйте этот способ для отрисовки HTML, не заключенного в HTML-теги. Без HTML или Razor тега Razor возникает ошибка среды выполнения.

Тег <text> хорошо подходит для контроля пробелов при отрисовке содержимого:

  • Отрисовывается только содержимое между тегами <text>.
  • В выходных данных HTML пробелы до или после тега <text> не отображаются.

Явный перенос строки

Для отрисовки оставшейся части строки в виде HTML внутри блока кода используйте синтаксис @::

@for (var i = 0; i < people.Length; i++)
{
    var person = people[i];
    @:Name: @person.Name
}

@: Без кода Razor создается ошибка среды выполнения.

Дополнительные @ символы в Razor файле могут вызвать ошибки компилятора при инструкциях позже в блоке. Эти дополнительные @ ошибки компилятора:

  • Может быть трудно понять, так как фактическая ошибка возникает до сообщаемой ошибки.
  • Распространено после объединения нескольких неявных и явных выражений в один блок кода.

Отрисовка условного атрибута

Razor Автоматически не удается указать атрибуты, которые не нужны. Если переданное значение или nullfalseатрибут не отображается.

Например, рассмотрим следующее razor:

<div class="@false">False</div>
<div class="@null">Null</div>
<div class="@("")">Empty</div>
<div class="@("false")">False String</div>
<div class="@("active")">String</div>
<input type="checkbox" checked="@true" name="true" />
<input type="checkbox" checked="@false" name="false" />
<input type="checkbox" checked="@null" name="null" />

Razor Предыдущая разметка создает следующий HTML-код:

<div>False</div>
<div>Null</div>
<div class="">Empty</div>
<div class="false">False String</div>
<div class="active">String</div>
<input type="checkbox" checked="checked" name="true">
<input type="checkbox" name="false">
<input type="checkbox" name="null">

Управляющие структуры

Управляющие структуры являются расширением блоков кода. Все аспекты блоков кода (переход на разметку, встроенный код C#) также относятся к следующим структурам.

Условий @if, else if, else, and @switch

@if контролирует, когда нужно запускать код:

@if (value % 2 == 0)
{
    <p>The value was even.</p>
}

Для else и else if символ @ не требуется:

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

В следующей разметке показано использование оператора switch:

@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;
}

Цикл @for, @foreach, @while, and @do while

Операторы выполнения цикла позволяют выполнять отрисовку шаблонного HTML. Отрисовка списка людей:

@{
    var people = new Person[]
    {
          new Person("Weston", 33),
          new Person("Johnathon", 41),
          ...
    };
}

Поддерживаются следующие операторы выполнения цикла:

@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);

Составной оператор @using

В C# оператор using позволяет обеспечить использование какого-то объекта. В Razorэтом же механизме используется для создания вспомогательных элементов HTML, содержащих дополнительное содержимое. В следующем коде вспомогательные функции HTML используют оператор @using для создания тега <form>:

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

@try, catch, finally

Обработка исключений выполняется так же, как в C#:

@try
{
    throw new InvalidOperationException("You did something invalid.");
}
catch (Exception ex)
{
    <p>The exception message: @ex.Message</p>
}
finally
{
    <p>The finally statement.</p>
}

@lock

Razor имеет возможность защитить критически важные разделы с помощью инструкций блокировки:

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

Комментарии

Razor поддерживает комментарии C# и HTML:

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

Код отображает следующий HTML:

<!-- HTML comment -->

Razor комментарии удаляются сервером перед отрисовки веб-страницы. Razor используется @* *@ для комментариев разделителей. Следующий код закомментирован, поэтому сервер не отрисовывает разметку:

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

Директивы

Razorдирективы представлены неявными выражениями с зарезервированными ключевое слово после символа@. Как правило, директива изменяет способ анализа представления или открывает доступ к дополнительным функциям.

Понимание того, как Razor создает код для представления, упрощает понимание работы директив.

@{
    var quote = "Getting old ain't for wimps! - Anonymous";
}

<div>Quote of the Day: @quote</div>

Код создает класс, аналогичный следующему:

public class _Views_Something_cshtml : RazorPage<dynamic>
{
    public override async Task ExecuteAsync()
    {
        var output = "Getting old ain't for wimps! - Anonymous";

        WriteLiteral("/r/n<div>Quote of the Day: ");
        Write(output);
        WriteLiteral("</div>");
    }
}

Далее в этой статье в разделе "Проверка класса C#", созданного Razor для представления , объясняется, как просмотреть созданный класс.

@attribute

Директива @attribute добавляет данный атрибут к классу созданной страницы или представления. В следующем примере добавляется атрибут [Authorize]:

@attribute [Authorize]

Директива @attribute также может использоваться для предоставления шаблона маршрута на основе констант в компоненте Razor . В следующем примере @page директива в компоненте заменяется @attribute директивой и шаблоном маршрута на основе констант в Constants.CounterRouteприложении, в котором установлено значение "/counter":

- @page "/counter"
+ @attribute [Route(Constants.CounterRoute)]

@code

Этот сценарий применяется только к Razor компонентам (.razor).

Блок @code позволяет Razor компоненту добавлять элементы C# (поля, свойства и методы) в компонент:

@code {
    // C# members (fields, properties, and methods)
}

Для Razor компонентов @code используется псевдоним @functions и рекомендуется.@functions Допускается использование нескольких блоков @code.

@functions

Директива @functions позволяет добавлять элементы C# (поля, свойства и методы) в создаваемый класс:

@functions {
    // C# members (fields, properties, and methods)
}

В Razor компонентах используйте его @functions@code для добавления элементов C#.

Например:

@functions {
    public string GetHello()
    {
        return "Hello";
    }
}

<div>From method: @GetHello()</div> 

Код создает следующую разметку HTML:

<div>From method: Hello</div>

Следующий код — созданный Razor класс C#:

using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Razor;

public class _Views_Home_Test_cshtml : RazorPage<dynamic>
{
    // Functions placed between here 
    public string GetHello()
    {
        return "Hello";
    }
    // And here.
#pragma warning disable 1998
    public override async Task ExecuteAsync()
    {
        WriteLiteral("\r\n<div>From method: ");
        Write(GetHello());
        WriteLiteral("</div>\r\n");
    }
#pragma warning restore 1998

Методы @functions служат в качестве методов создания шаблонов при наличии разметки:

@{
    RenderName("Mahatma Gandhi");
    RenderName("Martin Luther King, Jr.");
}

@functions {
    private void RenderName(string name)
    {
        <p>Name: <strong>@name</strong></p>
    }
}

Код отображает следующий HTML:

<p>Name: <strong>Mahatma Gandhi</strong></p>
<p>Name: <strong>Martin Luther King, Jr.</strong></p>

@implements

Директива @implements реализует интерфейс для созданного класса.

В следующем примере реализуется System.IDisposable, чтобы можно было вызывать метод Dispose:

@implements IDisposable

<h1>Example</h1>

@functions {
    private bool _isDisposed;

    ...

    public void Dispose() => _isDisposed = true;
}

@inherits

Директива @inherits позволяет полностью управлять классом, которому наследует представление:

@inherits TypeNameOfClassToInheritFrom

Следующий код — это пользовательский Razor тип страницы:

using Microsoft.AspNetCore.Mvc.Razor;

public abstract class CustomRazorPage<TModel> : RazorPage<TModel>
{
    public string CustomText { get; } = 
        "Gardyloo! - A Scottish warning yelled from a window before dumping" +
        "a slop bucket on the street below.";
}

В представлении отображается CustomText:

@inherits CustomRazorPage<TModel>

<div>Custom text: @CustomText</div>

Код отображает следующий HTML:

<div>
    Custom text: Gardyloo! - A Scottish warning yelled from a window before dumping
    a slop bucket on the street below.
</div>

@model и @inherits могут использоваться в одном представлении. @inherits может находиться в файле, импортируемом _ViewImports.cshtml представлением:

@inherits CustomRazorPage<TModel>

Следующий код показывает пример строго типизированного представления:

@inherits CustomRazorPage<TModel>

<div>The Login Email: @Model.Email</div>
<div>Custom text: @CustomText</div>

Если передать в модель "rick@contoso.com", представление создает следующую разметку HTML:

<div>The Login Email: rick@contoso.com</div>
<div>
    Custom text: Gardyloo! - A Scottish warning yelled from a window before dumping
    a slop bucket on the street below.
</div>

@inject

Директива @injectRazor позволяет странице внедрять службу из контейнера службы в представление. Дополнительные сведения: Внедрение зависимостей в представления.

@layout

Этот сценарий применяется только к Razor компонентам (.razor).

Директива @layout задает макет для routable Razor компонентов, имеющих директиву @page . Компоненты макета используются, чтобы избежать дублирования и несогласованности кода. Дополнительные сведения см. в разделе ASP.NET Макеты ядраBlazor.

@model

Этот сценарий применяется только к представлениям MVC и Razor страницам (.cshtml).

Директива @model определяет тип модели, передаваемой в представление или страницу:

@model TypeNameOfModel

В приложении ASP.NET Core MVC или Razor Pages, созданном с отдельными учетными записями пользователей, Views/Account/Login.cshtml содержится следующее объявление модели:

@model LoginViewModel

Созданный класс наследует от RazorPage<LoginViewModel>:

public class _Views_Account_Login_cshtml : RazorPage<LoginViewModel>

Razor предоставляет Model свойство для доступа к модели, переданной в представление:

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

Директива @model задает тип свойства Model. Директива указывает T в RazorPage<T> — созданном классе, на основе которого создается производное представление. Если директива @model не указана, свойство Model имеет тип dynamic. Дополнительные сведения см. в разделе Strongly typed models and the @model keyword.

@namespace

Директива @namespace:

  • Задает пространство имен класса созданной Razor страницы, представления MVC или Razor компонента.
  • Задает корневые производные пространства имен страниц, представлений или компонентов из ближайшего файла импорта в дереве каталогов , _ViewImports.cshtml (представления или страницы) или _Imports.razor (Razor компоненты).
@namespace Your.Namespace.Here

Пример Pages, показанный в следующей Razor таблице:

  • Каждый импорт Pages/_ViewImports.cshtmlстраницы.
  • Pages/_ViewImports.cshtml содержит @namespace Hello.World.
  • Каждая страница имеет Hello.World в качестве корня пространства имен.
Страница Пространство имен
Pages/Index.cshtml Hello.World
Pages/MorePages/Page.cshtml Hello.World.MorePages
Pages/MorePages/EvenMorePages/Page.cshtml Hello.World.MorePages.EvenMorePages

Предыдущие связи применяются к импорту файлов, используемых с представлениями и Razor компонентами MVC.

Если у нескольких файлов импорта есть директива @namespace, для задания корневого пространства имен используется файл, ближайший к странице, компоненту или представлению в дереве каталогов.

EvenMorePages Если папка в предыдущем примере содержит файл @namespace Another.Planet импорта (или Pages/MorePages/EvenMorePages/Page.cshtml файл содержит@namespace Another.Planet), результат показан в следующей таблице.

Страница Пространство имен
Pages/Index.cshtml Hello.World
Pages/MorePages/Page.cshtml Hello.World.MorePages
Pages/MorePages/EvenMorePages/Page.cshtml Another.Planet

@page

Директива @page имеет различные эффекты в зависимости от типа файла, в котором она используется. Директива:

@preservewhitespace

Этот сценарий применяется только к Razor компонентам (.razor).

Если задано false значение (по умолчанию), пробелы в отрисованной разметке из Razor компонентов (.razor) удаляются, если:

  • Они находятся в начале или конце элемента.
  • Они находятся в начале или конце параметра RenderFragment. Например, когда дочернее содержимое передается другому компоненту.
  • Они находятся в начале или конце блока кода C#, например @if и @foreach.

@rendermode

Этот сценарий применяется только к Razor компонентам (.razor).

Задает режим отрисовки Razor компонента:

  • InteractiveServer: применяет интерактивную отрисовку сервера с помощью Blazor Server.
  • InteractiveWebAssembly: применяет интерактивную отрисовку WebAssembly с помощью Blazor WebAssembly.
  • InteractiveAuto: Изначально применяет интерактивную отрисовку WebAssembly с помощью Blazor Server, а затем применяет интерактивную отрисовку WebAssembly с помощью WebAssembly при последующих посещениях после Blazor скачивания пакета.

Для экземпляра компонента:

<... @rendermode="InteractiveServer" />

В определении компонента:

@rendermode InteractiveServer

Примечание.

Blazor шаблоны включают статическую using директиву для RenderMode файла приложения _Imports (Components/_Imports.razor) для более @rendermode короткого синтаксиса:

@using static Microsoft.AspNetCore.Components.Web.RenderMode

Без предыдущей директивы компоненты должны явно указывать статический RenderMode класс в @rendermode синтаксисе:

<Dialog @rendermode="RenderMode.InteractiveServer" />

Дополнительные сведения, включая рекомендации по отключению предварительной подготовки с помощью атрибута директивы или директивы, см. в разделе ASP.NET Режимы отрисовки CoreBlazor.

@section

Этот сценарий применяется только к представлениям MVC и Razor страницам (.cshtml).

Директива @section используется в сочетании с макетами MVC и Pages, чтобы разрешить представлениям Razor или страницам отображать содержимое в разных частях HTML-страницы. Подробные сведения см. в статье Макет в ASP.NET Core.

@typeparam

Этот сценарий применяется только к Razor компонентам (.razor).

Директива @typeparam объявляет параметр универсального типа для созданного класса компонента:

@typeparam TEntity

Поддерживаются универсальные типы с ограничениями типов where:

@typeparam TEntity where TEntity : IEntity

Дополнительные сведения см. в следующих статьях:

@using

Директива @using добавляет директиву C# using в созданное представление:

@using System.IO
@{
    var dir = Directory.GetCurrentDirectory();
}
<p>@dir</p>

В Razor компонентах также определяет, @using какие компоненты находятся в область.

Атрибуты директивы

RazorАтрибуты директивы представлены неявными выражениями с зарезервированными ключевое слово после символа@. Атрибут директивы обычно изменяет способ синтаксического анализа элемента или включает различные функциональные возможности.

@attributes

Этот сценарий применяется только к Razor компонентам (.razor).

@attributes позволяет компоненту обрабатывать необъявленные атрибуты. Дополнительные сведения см. в разделе ASP.NET Splatting и произвольные параметры атрибута CoreBlazor.

@bind

Этот сценарий применяется только к Razor компонентам (.razor).

Привязка данных в компонентах выполняется с помощью атрибута @bind. Дополнительные сведения см. в разделе ASP.NET Привязка Blazorосновных данных.

@bind:culture

Этот сценарий применяется только к Razor компонентам (.razor).

@bind:culture Используйте атрибут с @bind атрибутом, чтобы обеспечить System.Globalization.CultureInfo синтаксический анализ и форматирование значения. Дополнительные сведения см. в статье Глобализация и локализация в ASP.NET Core Blazor.

@on{EVENT}

Этот сценарий применяется только к Razor компонентам (.razor).

Razor предоставляет функции обработки событий для компонентов. Дополнительные сведения см. в статье Обработка событий Blazor в ASP.NET Core.

@on{EVENT}:preventDefault

Этот сценарий применяется только к Razor компонентам (.razor).

Запрещает выполнение действия по умолчанию для события.

@on{EVENT}:stopPropagation

Этот сценарий применяется только к Razor компонентам (.razor).

Останавливает распространение события.

@key

Этот сценарий применяется только к Razor компонентам (.razor).

Атрибут директивы @key заставляет алгоритм сравнения компонентов гарантировать сохранение элементов или компонентов на основе значения ключа. Дополнительные сведения см. в разделе "Сохранение элементов, компонентов и моделей" в ASP.NET Core Blazor.

@ref

Этот сценарий применяется только к Razor компонентам (.razor).

Ссылки на компоненты (@ref) предоставляют способ ссылаться на экземпляр компонента, чтобы можно было выполнять команды для этого экземпляра. Дополнительные сведения см. в статье Компоненты Razor ASP.NET Core.

Делегаты с шаблонами Razor

Этот сценарий применяется только к представлениям MVC и Razor страницам (.cshtml).

Razor шаблоны позволяют определить фрагмент пользовательского интерфейса со следующим форматом:

@<tag>...</tag>

В следующем примере показано, как указать шаблонный делегат в качестве делегата RazorFunc<T,TResult>. Динамический тип указывается для параметра метода, инкапсулируемого делегатом. Тип объекта указывается в качестве возвращаемого значения делегата. Этот шаблон используется с List<T>объекта Pet, имеющим свойство Name.

public class Pet
{
    public string Name { get; set; }
}
@{
    Func<dynamic, object> petTemplate = @<p>You have a pet named <strong>@item.Name</strong>.</p>;

    var pets = new List<Pet>
    {
        new Pet { Name = "Rin Tin Tin" },
        new Pet { Name = "Mr. Bigglesworth" },
        new Pet { Name = "K-9" }
    };
}

Шаблон отрисовывается с использованием pets, предоставляемого оператором foreach:

@foreach (var pet in pets)
{
    @petTemplate(pet)
}

Отображенные выходные данные:

<p>You have a pet named <strong>Rin Tin Tin</strong>.</p>
<p>You have a pet named <strong>Mr. Bigglesworth</strong>.</p>
<p>You have a pet named <strong>K-9</strong>.</p>

Вы также можете указать встроенный Razor шаблон в качестве аргумента в метод. В следующем примере Repeat метод получает Razor шаблон. Метод использует этот шаблон для создания HTML-содержимого с повторениями элементов из списка:

@using Microsoft.AspNetCore.Html

@functions {
    public static IHtmlContent Repeat(IEnumerable<dynamic> items, int times,
        Func<dynamic, IHtmlContent> template)
    {
        var html = new HtmlContentBuilder();

        foreach (var item in items)
        {
            for (var i = 0; i < times; i++)
            {
                html.AppendHtml(template(item));
            }
        }

        return html;
    }
}

С использованием списка домашних животных из предыдущего примера метод Repeat вызывается следующим образом:

  • List<T> объекта Pet.
  • Количество повторений для каждого домашнего животного.
  • Встроенный шаблон, используемый для перечисления элементов неупорядоченного списка.
<ul>
    @Repeat(pets, 3, @<li>@item.Name</li>)
</ul>

Отображенные выходные данные:

<ul>
    <li>Rin Tin Tin</li>
    <li>Rin Tin Tin</li>
    <li>Rin Tin Tin</li>
    <li>Mr. Bigglesworth</li>
    <li>Mr. Bigglesworth</li>
    <li>Mr. Bigglesworth</li>
    <li>K-9</li>
    <li>K-9</li>
    <li>K-9</li>
</ul>

Вспомогательные функции тегов

Этот сценарий применяется только к представлениям MVC и Razor страницам (.cshtml).

Существует три директивы, которые относятся к вспомогательным функциям тегов.

Директива Function
@addTagHelper Делает вспомогательные функции тегов доступными в представлении.
@removeTagHelper Удаляет из представления вспомогательные функции тегов, добавленные ранее.
@tagHelperPrefix Задает префикс тега, который активирует поддержку вспомогательной функции тега и ее использования в явном виде.

Razorзарезервированные ключевое слово

Razorключевое слово

  • page
  • namespace
  • functions
  • inherits
  • model
  • section
  • helper (В настоящее время не поддерживается ASP.NET Core)

Razorключевое слово экранируются с @(Razor Keyword) помощью (например, @(functions)).

Ключевое слово C# Razor

  • case
  • do
  • default
  • for
  • foreach
  • if
  • else
  • lock
  • switch
  • try
  • catch
  • finally
  • using
  • while

Ключевое слово C# Razor необходимо дважды экранировать с помощью @(@C# Razor Keyword) (например, @(@case)). Первый @ экранирует Razor средство синтаксического анализа. а второй @ — для обхода C#.

Зарезервированные ключевое слово, не используемыеRazor

  • class

Проверка класса C#, созданного Razor для представления

Пакет Razor SDK обрабатывает компиляцию Razor файлов. По умолчанию созданные файлы кода не создаются. Чтобы включить создание файлов кода, задайте директиву EmitCompilerGeneratedFiles в файле проекта (.csproj) trueследующим образом:

<PropertyGroup>
  <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
</PropertyGroup>

При создании проекта 6.0 (net6.0) в Debug конфигурации Razor сборки пакет SDK создает obj/Debug/net6.0/generated/ каталог в корневом каталоге проекта. Его подкаталог содержит созданные Razor файлы кода страницы.

Пакет Razor SDK обрабатывает компиляцию Razor файлов. При создании проекта Razor пакет SDK создает obj/{BUILD CONFIGURATION}/{TARGET FRAMEWORK MONIKER}/Razor каталог в корневом каталоге проекта. Структура каталогов в каталоге Razor зеркало структуру каталогов проекта.

Рассмотрим следующую структуру каталогов в проекте ASP.NET Core Razor Pages 2.1:

 Areas/
   Admin/
     Pages/
       Index.cshtml
       Index.cshtml.cs
 Pages/
   Shared/
     _Layout.cshtml
   _ViewImports.cshtml
   _ViewStart.cshtml
   Index.cshtml
   Index.cshtml.cs

Создание проекта в Debug конфигурации дает следующий obj каталог:

 obj/
   Debug/
     netcoreapp2.1/
       Razor/
         Areas/
           Admin/
             Pages/
               Index.g.cshtml.cs
         Pages/
           Shared/
             _Layout.g.cshtml.cs
           _ViewImports.g.cshtml.cs
           _ViewStart.g.cshtml.cs
           Index.g.cshtml.cs

Чтобы просмотреть созданный класс для Pages/Index.cshtml, откройте obj/Debug/netcoreapp2.1/Razor/Pages/Index.g.cshtml.cs.

Поиск данных в представлениях и учет регистра

Обработчик Razor представлений выполняет поиск с учетом регистра для представлений. Однако фактический поиск зависит от используемой файловой системы.

  • Источник на основе файлов:
    • В операционных системах, файловые системы которых не учитывают регистр (например, Windows), поиск поставщика физических файлов не зависит от регистра. Например, return View("Test") результаты совпадений для /Views/Home/Test.cshtml, /Views/home/test.cshtmlа также любой другой вариант регистра.
    • В файловых системах, учитывающих регистр (например, в Linux, OSX и где используется EmbeddedFileProvider), поиск выполняется с учетом регистра. Например, return View("Test") в частности соответствует /Views/Home/Test.cshtml.
  • Предварительно скомпилированные представления: в ASP.NET Core 2.0 и более поздних версиях поиск в предварительно скомпилированных представлениях выполняется без учета регистра во всех операционных системах. Это поведение аналогично поведению поставщика физических файлов в Windows. Если два предварительно скомпилированных представления отличаются только регистром, результат поиска является недетерминированным.

Разработчикам рекомендуется использовать для файлов и каталогов тот же регистр, что и для:

  • имен областей, контроллеров и действий;
  • Razor Страниц.

Совпадающий регистр гарантирует, что развертываемые службы смогут находить свои представления вне зависимости от используемой файловой системы.

Импорт, используемый Razor

Следующие импорты создаются веб-шаблонами ASP.NET Core для поддержки Razor файлов:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.ViewFeatures;

Дополнительные ресурсы

Введение в ASP.NET веб-программирование с помощью синтаксиса Razor предоставляет множество примеров программирования с синтаксисомRazor.