Перейти к содержимому

Razor pages что это

  • автор:

Razor Pages

Начиная с версии 2.0 в ASP.NET Core была добавлена такая функциональность, как Razor Pages . Razor Pages предоставляют технологию, альтернативную системе Model-View-Controller. Razor Pages позволяют создавать страницы с кодом Razor, которые могут обрабатывать запросы. В некоторой степени эта функциональности напоминает работу веб-форм, которые представляли страницу с расширением aspx и имели файл логики на C#, связанный с данной страницей. В этом плане Razor Pages представляют альтернативу стандартной модели MVC для построения приложения.

Больше всего Razor Pages подходят для создания небольших приложений.

Для начала работы с Razor Pages создадим новый проект ASP.NET Core. При создании проекта укажем шаблон Web Application :

Razor Pages в ASP.NET Core

После создания проект будет иметь следующую структуру:

Проект Razor Pages в ASP.NET Core

Главным же отличием данного проекта от других типов проектов будет наличие папки Pages . Эта папка содержит все страницы Razor, которые есть в проекте по умолчанию. Каждая страница Razor представляет файл с расширением .cshtml и содержит смесь кода html и конструкций C#. По сути это те же самые представления, что используются в MVC. Но в отличие от MVC с каждой страницей Razor связан файл отделенного кода логики на C#. Например, с файлом Index.cshtml , который определяет визуальную часть с помощью синтаксиса Razor + HTML/CSS, связан файл Index.cshtml.cs , который определяет логику страницы или ее поведение с помощью кода C#. В какой-то степени эта модель похожа на то, что имеется в WPF или Xamarin Forms, где есть файл, который определяет визуальную часть, и есть связанный с ним файл кода, который определяет поведение.

По умолчанию в папке Pages имеются следующие файлы:

  • _Layout.cshtml : мастер-страница, в которую вставляются страницы Razor
  • _ViewStart.cshtml : задает мастер-страницу
  • _ViewImports.cshtml : определяет директивы Razor, которые добавляются на каждую страницу Razor
  • _ValidationScriptsPartial.cshtml : частичное представление, которое подключает js-скрипты валидации на стороне клиента
  • Index.cshtml , Error.cshtml и Privacy.cshtml : собственно страницы Razor, которые определяют визуальную часть страницы и логику обработки запроса.

Подключение Razor Pages

Для подключения сервисов Razor Pages применяется метод AddRazorPages . Например, во вновь созданном проекте мы можем увидеть в классе Startup в методе ConfigureServices подключение Razor Pages:

public void ConfigureServices(IServiceCollection services)

В действительности Razor Pages работают поверх фреймворка MVC, поэтому мы можем подключить и с помощью метода AddMvc() :

public void ConfigureServices(IServiceCollection services)

Однако AddMvc() подключает в целом всю возможную функциональность фреймворка MVC, в том числе возможность использования контроллеров с представлениями. Если мы не собираемся использовать контроллеры, то логично подключать Razor Pages с помощью метода AddRazorPages() .

Маршрутизация в RazorPages

Другим важным моментом является маршрутизация или как Razor Pages сопоставляются с запросами. По умолчанию проект с Razor Pages для обработки запросов используется конечные точки, то связку компонентов middleware EndpointMiddleware и EndpointRoutingMiddleware:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env) < if (env.IsDevelopment()) < app.UseDeveloperExceptionPage(); >else < app.UseExceptionHandler("/Error"); app.UseHsts(); >app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.UseAuthorization(); app.UseEndpoints(endpoints => < endpoints.MapRazorPages(); // Добавляем маршрутизацию для Razor Pages >); >

Непосредствено для связи с Razor Pages применяется метод endpoints.MapRazorPages() . В остальных аспектах класс Startup не отличается от того, что мы имеем в проекте MVC.

В итоге строка запроса URL будет сопоставляться с определенной страницей Razor на основании ее расположения в проекте в папке Pages. Примеры строк URL и сопоставленных с ними страниц:

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 в .cshtml Razor файлах отрисовывается сервером без изменений.

Синтаксис Razor

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

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

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

@@Username

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

@Username

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

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

@ < string message = "foreignObject example with Scalable Vector Graphics (SVG)"; >   

@message

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

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

@DateTime.Now

@DateTime.IsLeapYear(2016)

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

@await DoSomething("hello", "world")

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

@GenericMethod()

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

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

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

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

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

Last week this time: @(DateTime.Now - TimeSpan.FromDays(7))

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

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

Last week: @DateTime.Now - TimeSpan.FromDays(7)

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

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

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

@ < var joe = new Person("Joe", 33); >

Age@(joe.Age)

Без явного выражения

Age@joe.Age

обрабатывается как адрес электронной почты, и на выходе отображается

Age@joe.Age

. Если же текст написан как явное выражение, то вы получите

Age33

.

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

@(GenericMethod())

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

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

@("Hello World") 

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

<span>Hello World</span> 

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

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

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

@Html.Raw("Hello World") 

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

Hello World 

Razor Блоки кода

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

@ < var quote = "The future depends on what you do today. - Mahatma Gandhi"; >

@quote

@ < quote = "Hate cannot drive out hate, only love can do that. - Martin Luther King, Jr."; >

@quote

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

The future depends on what you do today. - Mahatma Gandhi

Hate cannot drive out hate, only love can do that. - Martin Luther King, Jr.

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

@< void RenderName(string name) < 

Name: @name

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

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

Name: Mahatma Gandhi

Name: Martin Luther King, Jr.

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

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

@< var inCSharp = true; 

Now in HTML, was in C# @inCSharp

>

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

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

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

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

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

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

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

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

@for (var i = 0; i

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

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

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

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

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

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

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

False
Null

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

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

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

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

@if (value % 2 == 0) < 

The value was even.

>

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

@if (value % 2 == 0) < 

The value was even.

> else if (value >= 1337) <

The value is large.

> else <

The value is odd and small.

>

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

@switch (value) < case 1: 

The value is 1!

break; case 1337:

Your number is 1337!

break; default:

Your number wasn't 1 or 1337.

break; >

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

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

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

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

Name: @person.Name

Age: @person.Age

>
@foreach (var person in people) < 

Name: @person.Name

Age: @person.Age

>
@ < var i = 0; >@while (i < people.Length) < var person = people[i]; 

Name: @person.Name

Age: @person.Age

i++; >
@ < var i = 0; >@do < var person = people[i]; 

Name: @person.Name

Age: @person.Age

i++; > while (i < people.Length);

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

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

@using (Html.BeginForm()) < 
Email:
>

@try, catch, finally

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

@try < throw new InvalidOperationException("You did something invalid."); >catch (Exception ex) < 

The exception message: @ex.Message

> finally <

The finally statement.

>

@lock

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

@lock (SomeLock) < // Do critical section work >

Комментарии

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

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

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

Директивы

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

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

@ < var quote = "Getting old ain't for wimps! - Anonymous"; >
Quote of the Day: @quote

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

public class _Views_Something_cshtml : RazorPage < public override async Task ExecuteAsync() < var output = "Getting old ain't for wimps! - Anonymous"; WriteLiteral("/r/n
Quote of the Day: "); Write(output); WriteLiteral("
"); > >

Далее в этой статье в разделе "Проверка класса 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"; >> 
From method: @GetHello()

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

From method: Hello

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

using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc.Razor; public class _Views_Home_Test_cshtml : RazorPage  < // Functions placed between here public string GetHello() < return "Hello"; >// And here. #pragma warning disable 1998 public override async Task ExecuteAsync() < WriteLiteral("\r\n
From method: "); Write(GetHello()); WriteLiteral("
\r\n"); > #pragma warning restore 1998

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

@ < RenderName("Mahatma Gandhi"); RenderName("Martin Luther King, Jr."); >@functions < private void RenderName(string name) < 

Name: @name

> >

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

Name: Mahatma Gandhi

Name: Martin Luther King, Jr.

@implements

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

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

@implements IDisposable 

Example

@functions < private bool _isDisposed; . public void Dispose() =>_isDisposed = true; >

@inherits

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

@inherits TypeNameOfClassToInheritFrom 

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

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

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

@inherits CustomRazorPage 
Custom text: @CustomText

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

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

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

@inherits CustomRazorPage

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

@inherits CustomRazorPage 
The Login Email: @Model.Email
Custom text: @CustomText

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

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

@inject

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

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

public class _Views_Account_Login_cshtml : RazorPage

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

The Login Email: @Model.Email

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

@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 имеет различные эффекты в зависимости от типа файла, в котором она используется. Директива:

  • .cshtml В файле указывается, что файл является страницейRazor. Дополнительные сведения см. в разделе "Пользовательские маршруты " и "Общие сведения о Razor страницах" в ASP.NET Core.
  • Указывает, что Razor компонент должен обрабатывать запросы напрямую. Дополнительные сведения см. в статье Маршрутизация ASP.NET Core Blazor и навигация.

@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 

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

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

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

Дополнительные сведения, включая рекомендации по отключению предварительной подготовки с помощью атрибута директивы или директивы, см. в разделе 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 

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

  • поддержка универсального типа компонента ASP.NET Core Razor
  • Шаблонные компоненты ASP.NET Core Blazor

@using

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

@using System.IO @ < var dir = Directory.GetCurrentDirectory(); >

@dir

В 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

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

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

@on:preventDefault

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

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

@on:stopPropagation

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

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

@key

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

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

@ref

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

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

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

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

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

public class Pet < public string Name < get; set; >> 
@ < FuncpetTemplate = @

You have a pet named @item.Name.

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

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

@foreach (var pet in pets)

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

You have a pet named Rin Tin Tin.

You have a pet named Mr. Bigglesworth.

You have a pet named K-9.

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

@using Microsoft.AspNetCore.Html @functions < public static IHtmlContent Repeat(IEnumerableitems, int times, Func template) < var html = new HtmlContentBuilder(); foreach (var item in items) < for (var i = 0; i < times; i++) < html.AppendHtml(template(item)); >> return html; > > 

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

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

  • Rin Tin Tin
  • Rin Tin Tin
  • Rin Tin Tin
  • Mr. Bigglesworth
  • Mr. Bigglesworth
  • Mr. Bigglesworth
  • K-9
  • K-9
  • K-9

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

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

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

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

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

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

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

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

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

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

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

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

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

 true  

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

Пакет Razor SDK обрабатывает компиляцию Razor файлов. При создании проекта Razor пакет SDK создает obj///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 .

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

    • имен областей, контроллеров и действий;
    • 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.

    Совместная работа с нами на GitHub

    Источник этого содержимого можно найти на GitHub, где также можно создавать и просматривать проблемы и запросы на вытягивание. Дополнительные сведения см. в нашем руководстве для участников.

    Что такое Razor Pages?

    Функционал Razor Pages появился на платформе ASP.NET Core ещё в 2019 году. По сути, Razor Page – это страница, состоящая из стандартной разметки и бэкенд-класса, который одновременно выступает моделью и контроллером. Данный функционал позволяет создавать страницы с кодом Razor и обрабатывать запросы. Другими словами, Razor Pages – это близкий аналог веб-форм, они представляют собой альтернативное решение для создания приложений, в первую очередь, небольших.

    Что изменилось?

    Для наших ASP.NET Core-компонентов, входящих в состав продуктов Reports.WEB и Dashboards.WEB появилась возможность создавать веб-приложения и проекты с использованием Razor Pages. В созданных проектах будут доступны все инструменты создания, отображения, преобразования отчетов и дашбордов. Доступны все уже существующие опции компонентов и настройки их внешнего вида, возможность построения и экспортирования отчета при помощи кода на стороне сервера.

    Пример работы

    До версии 2023.1, наши компоненты для ASP.NET Core работали только с использованием MVC-технологии, которая, естественно, имеет свои плюсы и минусы. Для сравнения, чтобы отобразить компонент на веб-странице с использованием MVC, нужно было определить разметку компонента и его опции на View, затем определить все необходимые действия в Controller, при необходимости нужно было определить структуру данных в Model:

    View:

    @Html.StiNetCoreViewer(new StiNetCoreViewerOptions() < Actions = < GetReport = "GetReport", ViewerEvent = "ViewerEvent" >>)

    Controller:

    public IActionResult GetReport() < var report = new StiReport(); report.LoadDocument(StiNetCoreHelper.MapPath(this, "Reports/SimpleList.mdc")); return StiNetCoreViewer.GetReportResult(this, report); >public IActionResult ViewerEvent()

    При использовании технологии Razor Pages, весь код может быть размещен на одной странице, а вместо действий контроллера определяются события для GET и POST запросов. Например, тот же код развертывания нашего компонента выглядит следующим образом:

    @Html.StiNetCoreViewer(new StiNetCoreViewerOptions() < Actions = < GetReport = "GetReport", ViewerEvent = "ViewerEvent" >>) public IActionResult OnPostGetReport() < var report = new StiReport(); report.LoadDocument(StiNetCoreHelper.MapPath(this, "Reports/SimpleList.mdc")); return StiNetCoreViewer.GetReportResult(this, report); >public IActionResult OnGetViewerEvent() < return StiNetCoreViewer.ViewerEventResult(this); >public IActionResult OnPostViewerEvent()

    Код для Razor Pages имеет очень похожую структуру, но существует ряд отличий:

    • Вместо действий используются события обработки запросов;
    • Вместо контроллера на вход результирующих функций передается объект страницы;
    • В качестве названия события используется стандартный префикс типа запроса OnGet либо OnPost, и заданное в настройках компонента имя события.

    Дополнительная информация

    Мы постарались максимально упростить развертывание компонента, и сохранить совместимость с предыдущими версиями, поэтому не требуется больших изменений кода для перехода на Razor Pages. Мы обновили документацию и добавили множество примеров. Мы очень надеемся, что всё это значительно упростит интеграцию компонентов в ваше приложение, а в случае перехода с MVC на Razor Pages, не вызовет никаких затруднений.

    Если у вас остались вопросы, свяжитесь с нами.

    By using this website, you agree to the use of cookies for analytics and personalized content. Cookies store useful information on your computer to help us improve efficiency and usability. For more information, please read the privacy policy and cookie policy.

    Введение в Razor Pages в ASP.NET Core

    Это не последняя версия этой статьи. В текущем выпуске см . версию .NET 8 этой статьи.

    [!IMPORTANT] > This information relates to a pre-release product that may be substantially modified before it's commercially released. Microsoft makes no warranties, express or implied, with respect to the information provided here. > > For the current release, see the [.NET 8 version of this article](?view=aspnetcore-8.0&preserve-view=true). . moniker-end -->

    Razor Pages делает создание кодов сценариев для страниц проще и эффективнее по сравнению с использованием контроллеров и представлений.

    Если вам нужно руководство, использующее подход "модель-представление-контроллер", см. статью Начало работы с MVC в ASP.NET Core.

    Этот документ содержит вводные сведения о Razor Pages. Это не пошаговое руководство. Если некоторые разделы покажутся вам слишком сложными, см. Начало работы с Razor Pages. Общие сведения об ASP.NET Core см. в разделе Введение в ASP.NET Core.

    Необходимые компоненты

    • Visual Studio
    • Visual Studio Code
    • Visual Studio для Mac
    • Visual Studio 2022 с рабочей нагрузкой ASP.NET и веб-разработка.
    • Пакет SDK для .NET 6.0
    • Visual Studio Code
    • C# для Visual Studio Code (последняя версия)
    • Пакет SDK для .NET 6.0

    Для функций разработки ASP.NET Core, таких как создание проекта, в инструкциях Visual Studio Code используется .NET CLI. Эти инструкции можно выполнять на macOS, Linux или Windows и в любом редакторе кода. При использовании редактора, отличного от Visual Studio Code, может потребоваться внести незначительные изменения.

    • Visual Studio Code с набором средств разработки C# и связанными расширениями, такими как .NET MAUI и Unity.
    • Интегрированная среда разработки Visual Studio, запущенная в Windows на виртуальной машине Mac.
    • Интегрированная среда разработки Visual Studio, запущенная в Windows на виртуальной машине в облаке.

    Дополнительные сведения см. в Visual Studio для Mac объявлении о выходе на пенсию.

    Создание проекта Razor Pages

    • Visual Studio
    • Visual Studio Code
    • Visual Studio для Mac

    Подробные инструкции по созданию проекта Razor Pages см. в статье Начало работы с Razor Pages.

    Из командной строки выполните команду dotnet new webapp .

    Подробные инструкции по созданию проекта Razor Pages см. в статье Начало работы с Razor Pages.

    Razor Pages

    Razor Страницы включены в Program.cs :

    var builder = WebApplication.CreateBuilder(args); builder.Services.AddRazorPages(); var app = builder.Build(); if (!app.Environment.IsDevelopment()) < app.UseExceptionHandler("/Error"); app.UseHsts(); >app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.UseAuthorization(); app.MapRazorPages(); app.Run(); 

    В предыдущем коде:

    • AddRazorPages добавляет в приложение службы для Razor Pages.
    • MapRazorPages добавляет в IEndpointRouteBuilder конечные точки для Razor Pages.

    Рассмотрим простую страницу:

    @page 

    Hello, world!

    The time on the server is @DateTime.Now

    Приведенный выше код выглядит как Razor файл представления, используемый в приложениях ASP.NET Core с контроллерами и представлениями. Он отличается от него только директивой @page . @page превращает файл в действие MVC, обрабатывая запросы напрямую без контроллера. @page должна быть первой директивой Razor на странице. @page влияет на поведение всех остальных конструкций Razor. Имена файлов Razor Pages содержат суффикс .cshtml .

    Похожая страница с использованием класса PageModel показана в следующих двух файлах. Файл Pages/Index2.cshtml :

    @page @using RazorPagesIntro.Pages @model Index2Model 

    Separate page model

    @Model.Message

    Модель страницы Pages/Index2.cshtml.cs :

    using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.Extensions.Logging; using System; namespace RazorPagesIntro.Pages < public class Index2Model : PageModel < public string Message < get; private set; >= "PageModel in C#"; public void OnGet() < Message += $" Server time is < DateTime.Now >"; > > > 

    По соглашению файл класса имеет то же имя, PageModel что Razor и файл page с .cs добавленным. Например, предыдущая страница Razor Pages называется Pages/Index2.cshtml . Файл, содержащий класс PageModel , называется Pages/Index2.cshtml.cs .

    Сопоставления URL-адресов со страницами определяются расположением конкретной страницы в файловой системе. В приведенной ниже таблице показаны пути Razor Pages и соответствующие URL-адреса.

    Имя файла и путь Соответствующий URL
    /Pages/Index.cshtml / или /Index
    /Pages/Contact.cshtml /Contact
    /Pages/Store/Contact.cshtml /Store/Contact
    /Pages/Store/Index.cshtml /Store или /Store/Index
    • Среда выполнения по умолчанию ищет файлы Razor Pages в папке Pages.
    • Если в URL-адресе не указана конкретная страница, по умолчанию открывается страница Index .

    Создание простой формы

    Razor Pages предназначена для упрощения реализации типовых шаблонов, которые используются в браузерах, при создании приложения. Привязки моделей, вспомогательные функции тегов и вспомогательные методы HTML работают со свойствами, определенными в классе Razor Pages. Рассмотрим страницу с простой формой связи для модели Contact .

    Примеры в этом документе DbContext инициализированы в файле Program.cs .

    Для работы с базой данных в памяти требуется пакет NuGet Microsoft.EntityFrameworkCore.InMemory .

    using Microsoft.EntityFrameworkCore; using RazorPagesContacts.Data; var builder = WebApplication.CreateBuilder(args); builder.Services.AddRazorPages(); builder.Services.AddDbContext(options => options.UseInMemoryDatabase("name")); var app = builder.Build(); if (!app.Environment.IsDevelopment()) < app.UseExceptionHandler("/Error"); app.UseHsts(); >app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.UseAuthorization(); app.MapRazorPages(); app.Run(); 
    using System.ComponentModel.DataAnnotations; namespace RazorPagesContacts.Models < public class Customer < public int Id < get; set; >[Required, StringLength(10)] public string? Name < get; set; >> > 

    Контекст базы данных:

    using Microsoft.EntityFrameworkCore; namespace RazorPagesContacts.Data < public class CustomerDbContext : DbContext < public CustomerDbContext (DbContextOptionsoptions) : base(options) < >public DbSet Customer => Set(); > > 

    Файл представления Pages/Customers/Create.cshtml :

    @page @model RazorPagesContacts.Pages.Customers.CreateModel @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 

    Enter a customer name:

    Name:

    Модель страницы Pages/Customers/Create.cshtml.cs :

    public class CreateModel : PageModel < private readonly Data.CustomerDbContext _context; public CreateModel(Data.CustomerDbContext context) < _context = context; >public IActionResult OnGet() < return Page(); >[BindProperty] public Customer? Customer < get; set; >public async Task OnPostAsync() < if (!ModelState.IsValid) < return Page(); >if (Customer != null) _context.Customer.Add(Customer); await _context.SaveChangesAsync(); return RedirectToPage("./Index"); > > 

    Как правило, класс PageModel называется Model и находится в том же пространстве имен, что и страница.

    Класс PageModel позволяет разделять логику страницы и ее представление. Он определяет обработчики страницы для запросов, отправляемых на страницу, а также данные для ее визуализации. Это разделение позволяет:

    • управлять зависимостями страниц с помощью внедрения зависимостей.
    • Модульное тестирование

    Страница содержит метод обработчика OnPostAsync , который выполняется по запросам POST (когда пользователь публикует форму). Можно добавить методы обработчика для любой HTTP-команды. Ниже перечислены наиболее распространенные обработчики.

    • OnGet инициализирует нужное состояние для страницы. В приведенном выше коде метод OnGet отображает страницу Razor CreateModel.cshtml .
    • OnPost обрабатывает отправку формы.

    Суффикс имени Async является необязательным, но часто применяется в соответствии с соглашением для асинхронных функций. Этот код типичен для Razor Pages.

    Если вы знакомы с приложениями ASP.NET, использующими контроллеры и представления:

    • Код OnPostAsync в предыдущем примере похож на стандартный код контроллера.
    • Большинство примитивов MVC, включая привязку модели, проверку и результаты действий, одинаково работают с контроллерами и Razor Pages.

    Предыдущий метод OnPostAsync :

    [BindProperty] public Customer? Customer < get; set; >public async Task OnPostAsync() < if (!ModelState.IsValid) < return Page(); >if (Customer != null) _context.Customer.Add(Customer); await _context.SaveChangesAsync(); return RedirectToPage("./Index"); > 

    Простая схема OnPostAsync :

    Проверка на наличие ошибок проверки.

    • Если ошибок нет, сохранение данных и перенаправление.
    • Если есть ошибки, отображение страницы с сообщениями проверки. Зачастую ошибки выявляются при проверке в клиенте и не передаются на сервер.

    Файл представления Pages/Customers/Create.cshtml :

    @page @model RazorPagesContacts.Pages.Customers.CreateModel @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 

    Enter a customer name:

    Name:

    Отрисованный HTML из Pages/Customers/Create.cshtml :

    Enter a customer name:

    Name: " />

    В приведенном выше коде, разместив форму:

    • С допустимыми данными:
      • Метод обработчика OnPostAsync вызывает вспомогательный метод RedirectToPage. RedirectToPage возвращает экземпляр RedirectToPageResult. RedirectToPage :
        • Является результатом действия.
        • Аналогичен RedirectToAction или RedirectToRoute (используется в контроллерах и представлениях).
        • Настраивается для страниц. В приведенном выше примере он выполняет перенаправление на корневую страницу индекса ( /Index ). Более подробно RedirectToPage рассматривается в разделе Создание URL для страниц.
        • Метод обработчика OnPostAsync вызывает вспомогательный метод Page. Page возвращает экземпляр PageResult. Возвращение Page аналогично тому, как действия в контроллерах возвращают View . PageResult — тип возвращаемого значения по умолчанию для метода обработчика. Метод обработчика, вернувший void , визуализирует страницу.
        • В предыдущем примере публикация формы без значения приводит к тому, что ModelState.IsValid возвращает значение false. В этом примере на клиенте не отображаются ошибки проверки. Обработка ошибок проверки рассматривается далее в этом документе.
        [BindProperty] public Customer? Customer < get; set; >public async Task OnPostAsync() < if (!ModelState.IsValid) < return Page(); >if (Customer != null) _context.Customer.Add(Customer); await _context.SaveChangesAsync(); return RedirectToPage("./Index"); > 
        • Данные не отправляются на сервер.
        • Проверка на стороне клиента описана далее в этом документе.

        Для указания согласия на привязку модели в свойстве Customer используется атрибут [BindProperty] :

        [BindProperty] public Customer? Customer < get; set; >public async Task OnPostAsync() < if (!ModelState.IsValid) < return Page(); >if (Customer != null) _context.Customer.Add(Customer); await _context.SaveChangesAsync(); return RedirectToPage("./Index"); > 

        [BindProperty] не следует использовать в моделях, содержащих свойства, которые не должны изменяться клиентом. Дополнительные сведения см. в этом разделе.

        По умолчанию Razor привязывает свойства ко всем командам, кроме GET . Привязка к свойствам устраняет необходимость в написании кода для преобразования данных HTTP в тип модели. Привязка уменьшает код за счет того, что для визуализации полей формы ( ) и получения входных данных используется одно и то же свойство.

        В целях безопасности вам следует задать привязку данных запроса GET к свойствам страничной модели. Проверьте введенные данные пользователя, прежде чем сопоставлять их со свойствами. Привязка GET полезна при обращении к сценариям, использующим строку запроса или значения маршрутов.

        Чтобы привязать свойство к запросам GET , задайте для свойства SupportsGet атрибута [BindProperty] значение true :

        [BindProperty(SupportsGet = true)] 

        Pages/Customers/Create.cshtml Просмотр файла представления:

        @page @model RazorPagesContacts.Pages.Customers.CreateModel @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 

        Enter a customer name:

        Name:
        • В приведенном выше коде вспомогательная функция тега вводапривязывает элемент HTML к выражению модели Customer.Name .
        • Директива @addTagHelper обеспечивает доступность вспомогательных функций тегов.

        Домашняя страница.

        Index.cshtml является домашней страницей:

        @page @model RazorPagesContacts.Pages.Customers.IndexModel @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 

        Contacts home page

        @if (Model.Customers != null) < foreach (var contact in Model.Customers) < > >
        ID Name
        @contact.Id @contact.Name --> Edit | --> --> -->
        Create New

        Связанный класс PageModel ( Index.cshtml.cs ):

        public class IndexModel : PageModel < private readonly Data.CustomerDbContext _context; public IndexModel(Data.CustomerDbContext context) < _context = context; >public IList? Customers < get; set; >public async Task OnGetAsync() < Customers = await _context.Customer.ToListAsync(); >public async Task OnPostDeleteAsync(int id) < var contact = await _context.Customer.FindAsync(id); if (contact != null) < _context.Customer.Remove(contact); await _context.SaveChangesAsync(); >return RedirectToPage(); > > 

        Файл Index.cshtml содержит следующую разметку:

        Вспомогательный тег привязки использовал атрибут asp-route- для создания ссылки на страницу редактирования. Эта ссылка содержит данные о маршруте с идентификатором контактного лица. Например, https://localhost:5001/Edit/1 . Вспомогательные функции тегов позволяют серверному коду участвовать в создании и отображении HTML-элементов в файлах Razor.

        Файл Index.cshtml содержит разметку для создания кнопки удаления для каждого контакта клиента:

         
         

        Во время обработки кнопки удаления в HTML ее formaction включает параметры для следующего:

        • Идентификатор контакта клиента, указанный атрибутом asp-route-id .
        • Параметр handler , указанный атрибутом asp-page-handler .

        При выборе кнопки на сервер отправляется запрос формы POST . По соглашению имя метода обработчика выбирается на основе значения параметра handler в соответствии со схемой OnPost[handler]Async .

        Так как handler — delete в этом примере, метод обработчика OnPostDeleteAsync используется для обработки запроса POST . Если asp-page-handler имеет другое значение, например remove , выбирается метод обработчика с именем OnPostRemoveAsync .

        public async Task OnPostDeleteAsync(int id) < var contact = await _context.Customer.FindAsync(id); if (contact != null) < _context.Customer.Remove(contact); await _context.SaveChangesAsync(); >return RedirectToPage(); > 
        • Получает id из строки запроса.
        • Отправляет в базу данных запрос контакта клиента с FindAsync .
        • Если контакт клиента найден, он удаляется, и база данных обновляется.
        • Вызывает RedirectToPage для перенаправления на корневую страницу индекса ( /Index ).

        Файл Edit.cshtml

        @page "" @model RazorPagesContacts.Pages.Customers.EditModel @ < ViewData["Title"] = "Edit"; >

        Edit

        Customer

        Back to List
        @section Scripts < @>

        Первая строка содержит директиву @page "" . Ограничение маршрутизации "" указывает, что страница должна принимать обращенные к ней запросы, которые содержат данные маршрутизации int . Если запрос к странице не содержит данные о маршруте, которые можно конвертировать в int , среда выполнения возвращает ошибку HTTP 404 (не найдено). Чтобы сделать идентификатор необязательным, добавьте ? к ограничению маршрута:

        @page "" 
        public class EditModel : PageModel < private readonly RazorPagesContacts.Data.CustomerDbContext _context; public EditModel(RazorPagesContacts.Data.CustomerDbContext context) < _context = context; >[BindProperty] public Customer? Customer < get; set; >public async Task OnGetAsync(int? id) < if (id == null) < return NotFound(); >Customer = await _context.Customer.FirstOrDefaultAsync(m => m.Id == id); if (Customer == null) < return NotFound(); >return Page(); > // To protect from overposting attacks, enable the specific properties you want to bind to. // For more details, see https://aka.ms/RazorPagesCRUD. public async Task OnPostAsync() < if (!ModelState.IsValid) < return Page(); >if (Customer != null) < _context.Attach(Customer).State = EntityState.Modified; try < await _context.SaveChangesAsync(); >catch (DbUpdateConcurrencyException) < if (!CustomerExists(Customer.Id)) < return NotFound(); >else < throw; >> > return RedirectToPage("./Index"); > private bool CustomerExists(int id) < return _context.Customer.Any(e =>e.Id == id); > > 

        Проверка

        • Декларативно задаются в классе Model.
        • Применяются везде в приложении.

        Пространство имен System.ComponentModel.DataAnnotations предоставляет набор встроенных атрибутов проверки, которые декларативно применяются к классу или свойству. Кроме того, DataAnnotations содержит атрибуты форматирования (такие как [DataType] ), которые обеспечивают форматирование и не предназначены для проверки.

        Рассмотрим модель Customer :

        using System.ComponentModel.DataAnnotations; namespace RazorPagesContacts.Models < public class Customer < public int Id < get; set; >[Required, StringLength(10)] public string? Name < get; set; >> > 

        С помощью следующего Create.cshtml файла представления:

        @page @model RazorPagesContacts.Pages.Customers.CreateModel @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 

        Validation: customer name:

        Name:
        • Включает jQuery и скрипты проверки jQuery.
        • Использует вспомогательные функции тегови для включения следующего:
          • Проверка на стороне клиента.
          • Отображение ошибок при проверке.

          Enter a customer name:

          Name: " />

          При публикации формы создания без значения имени в форме отображается сообщение об ошибке: "Поле имени является обязательным". Если на клиенте включен JavaScript, браузер отображает ошибку без отправки на сервер.

          Атрибут [StringLength(10)] создает data-val-length-max="10" в отображаемом HTML-коде. data-val-length-max не дает браузерам ввести больше заданной максимальной длины. Если для изменения и воспроизведения записи используется средство, например Fiddler, выполните следующие действия:

          • С именем, превышающим 10.
          • Возвращается сообщение об ошибке: "Имя поля должно быть строкой с максимальной длиной 10".

          Рассмотрим следующую модель Movie :

          using System; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; namespace RazorPagesMovie.Models < public class Movie < public int ID < get; set; >[StringLength(60, MinimumLength = 3)] [Required] public string Title < get; set; >[Display(Name = "Release Date")] [DataType(DataType.Date)] public DateTime ReleaseDate < get; set; >[Range(1, 100)] [DataType(DataType.Currency)] [Column(TypeName = "decimal(18, 2)")] public decimal Price < get; set; >[RegularExpression(@"^[A-Z]+[a-zA-Z\s]*$")] [Required] [StringLength(30)] public string Genre < get; set; >[RegularExpression(@"^[A-Z]+[a-zA-Z0-9""'\s-]*$")] [StringLength(5)] [Required] public string Rating < get; set; >> > 

          Атрибуты проверки определяют поведение для свойств модели, к которым они применяются:

          • Атрибуты Required и MinimumLength указывают, что свойство должно иметь значение. Тем не менее, чтобы удовлетворить требованиям проверки, пользователю достаточно ввести пробел.
          • Атрибут RegularExpression ограничивает набор допустимых для ввода символов. В приведенном выше коде в Genre:
            • должны использоваться только буквы;
            • первая буква должна быть прописной; пробелы, цифры и специальные символы не допускаются.
            • первый символ должен быть прописной буквой;
            • допускаются специальные символы и цифры, а также последующие пробелы. Значение "PG-13" допустимо для рейтинга, но недопустимо для жанра.

            На странице создания для модели Movie отображаются ошибки с недопустимыми значениями:

            Movie view form with multiple jQuery client-side validation errors

            Дополнительные сведения см. в разделе:

            • Добавление проверки в приложение Movie
            • Проверка модели в ASP.NET Core.

            Изоляция CSS

            Изоляция стилей CSS для отдельных страниц, представлений и компонентов, чтобы сократить или избежать следующего:

            • Зависимости от глобальных стилей, которые могут быть сложными в обслуживании.
            • Конфликты стилей во вложенном содержимом.

            Чтобы добавить CSS-файл с заданной областью для страницы или представления, поместите стили CSS в сопутствующий файл .cshtml.css , имя которого соответствует имени файла .cshtml . В следующем примере файл Index.cshtml.css предоставляет стили CSS, которые применяются только к представлению или странице Index.cshtml .

            Pages/Index.cshtml.css (Razor Pages) или Views/Index.cshtml.css (MVC):

            Изоляция CSS выполняется во время сборки. Платформа повторно создает селекторы CSS в соответствии с разметкой, отображаемой на страницах или в представлениях приложения. Созданные повторно стили CSS объединяются и создаются как статический ресурс .styles.css . Заполнитель — это имя сборки проекта. Ссылка на объединенные стили CSS помещается в макет приложения.

            В содержимом файла Pages/Shared/_Layout.cshtml приложения (Razor Pages) или Views/Shared/_Layout.cshtml (MVC) приложения добавьте ссылку на объединенные стили CSS или подтвердите ее наличие:

            .styles.css" /> 

            В следующем примере имя сборки приложения — WebApp :

            Стили, определенные в файле CSS с заданной областью, применяются только к отображаемым выходным данным соответствующего файла. В предыдущем примере все объявления CSS h1 , определенные в других областях приложения, не будут конфликтовать со стилем заголовка Index . Правила каскадов и наследования стилей CSS и дальше действуют для файлов CSS с заданной областью. Например, стили, примененные непосредственно к элементу в файле Index.cshtml , переопределяют стили файла CSS с заданной областью в Index.cshtml.css .

            Чтобы обеспечить изоляцию стиля CSS при выполнении объединения, импорт CSS в блоки кода Razor не поддерживается.

            Изоляция CSS применяется только к элементам HTML. Изоляция CSS не поддерживается для вспомогательных функций тегов.

            В объединенном файле CSS каждая страница, представление или компонент Razor связаны с идентификатором области в формате b- , где заполнитель представляет собой строку из десяти символов, сгенерированную платформой. В следующем примере представлен стиль для предыдущего элемента на странице Index приложения Razor Pages:

            /* /Pages/Index.cshtml.rz.scp.css */ h1[b-3xxtam6d07]

            На странице Index , где применяется стиль CSS из объединенного файла, идентификатор области добавляется как атрибут HTML:

            Идентификатор является уникальным для приложения. Во время сборки создается пакет проектов с использованием соглашения /Project.lib.scp.css , где заполнитель является базовым путем к статическим веб-ресурсам.

            Если используются другие проекты, такие как пакеты NuGet или библиотеки классов Razor, то объединенный файл:

            • ссылается на стили с помощью импорта CSS;
            • не публикуется как статический веб-ресурс приложения, использующего стили.

            Поддержка препроцессоров CSS

            Препроцессоры CSS полезны для улучшения разработки CSS с помощью таких функций, как переменные, вложенность, модули, примеси и наследование. Хотя изоляция CSS изначально не поддерживает препроцессоры CSS, такие как Sass и Less, интеграция препроцессоров CSS происходит без проблем, так как компиляция препроцессора выполняется до того, как платформа перезаписывает селекторы CSS в процессе сборки. С помощью Visual Studio, например, настройте существующую компиляцию препроцессора в качестве задачи перед сборкой в диспетчере выполнения задач Visual Studio.

            Многие сторонние пакеты NuGet, такие как AspNetCore.SassCompiler , могут компилировать файлы SASS и SCSS в начале процесса сборки перед выполнением изоляции CSS, и дополнительная настройка не требуется.

            Конфигурация изоляции CSS

            Изоляция CSS позволяет настраивать некоторые сложные сценарии, например включающих зависимости от существующих инструментов или рабочих процессов.

            Настройка формата идентификатора области

            В этом разделе заполнитель — либо Pages для приложений Razor Pages, либо Views для приложений MVC.

            По умолчанию идентификаторы областей используют формат b- , где заполнитель — это строка из десяти символов, сгенерированная платформой. Чтобы настроить формат идентификатора области, измените шаблон в файле проекта:

             /Index.cshtml.css" CssScope="custom-scope-identifier" /> 

            В предыдущем примере CSS, сформированный для Index.cshtml.css , изменяет свой идентификатор области с b- на custom-scope-identifier .

            Используйте идентификаторы областей, чтобы обеспечить наследование файлов CSS с назначенной областью. В следующем примере файла проекта файл BaseView.cshtml.css содержит общие стили для представлений. Файл DerivedView.cshtml.css наследует эти стили.

             /BaseView.cshtml.css" CssScope="custom-scope-identifier" /> /DerivedView.cshtml.css" CssScope="custom-scope-identifier" /> 

            Используйте оператор подстановочного знака ( * ), чтобы предоставить идентификаторы областей для нескольких файлов:

             /*.cshtml.css" CssScope="custom-scope-identifier" /> 

            Изменение базового пути для статических веб-ресурсов

            Файл CSS с заданной областью создается в корне приложения. Чтобы изменить путь по умолчанию, используйте свойство StaticWebAssetBasePath в файле проекта. В следующем примере файл CSS с заданной областью и остальные ресурсы приложения размещаются по пути _content :

             _content/$(PackageId)  

            Отключение автоматического объединения

            Чтобы отказаться от того, как платформа публикует и загружает файлы с заданной областью во время выполнения, используйте свойство DisableScopedCssBundling . При использовании этого свойства за получение изолированных файлов CSS из каталога obj и их публикацию и загрузку во время выполнения отвечают другие средства или процессы:

             true  

            Поддержка библиотеки классов Razor (RCL)

            Когда библиотека классов Razor (RCL) предоставляет изолированные стили, атрибут href тега указывает на /.bundle.scp.css со следующими заполнителями:

            • : базовый путь статического веб-ресурса.
            • : идентификатор пакета библиотеки. Если идентификатор пакета не указан в файле проекта, идентификатору пакета по умолчанию присваивается имя сборки проекта.

            В следующем примере :

            • Базовый путь к статическому веб-ресурсу — _content/ClassLib .
            • Имя сборки библиотеки классов — ClassLib .

            Pages/Shared/_Layout.cshtml (Razor Pages) или Views/Shared/_Layout.cshtml (MVC):

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

            • Многоразовый интерфейс Razor в библиотеках классов в ASP.NET Core
            • Использование компонентов ASP.NET Core Razor из библиотеки классов Razor (RCL)

            Сведения об изоляции CSS в Blazor см. в статье Изоляция CSS Blazor в ASP.NET Core.

            Обработка запросов HEAD с помощью вызова резервного обработчика OnGet

            Запросы HEAD позволяют получать заголовки для определенного ресурса. В отличие от запросов GET запросы HEAD не возвращают текст ответа.

            Обработчик OnHead обычно создается и вызывается для выполнения запросов HEAD :

            Если обработчик OnHead не определен, Razor Pages выполнит вызов обработчика OnGet .

            XSRF/CSRF и Razor Pages

            В Razor Pages реализована проверка для защиты от подделки. FormTagHelper вставляет маркеры защиты от подделки в элементы HTML-форм.

            Использование макетов, частичных реплик, шаблонов и вспомогательных функций тегов с Razor Pages

            Pages работает со всеми функциями подсистемы просмотра Razor. Макеты, частичные реплики, шаблоны, вспомогательные функции тегов, _ViewStart.cshtml и _ViewImports.cshtml одинаково работают для обычных представлений Razor.

            Давайте упростим нашу страницу с помощью некоторых из этих функций.

            Добавьте страницу макета в Pages/Shared/_Layout.cshtml :

               RP Sample  Home Create Customers 
            @RenderBody()
            • управляет макетом каждой страницы (кроме страниц с отказом от макета);
            • импортирует HTML-структуры, такие как JavaScript и таблицы стилей.
            • Содержимое страницы Razor отображается в том месте, где вызывается @RenderBody() .

            Дополнительные сведения см. здесь.

            Свойство макета задается в Pages/_ViewStart.cshtml :

            Макет хранится в папке Pages/Shared. Pages ищет другие представления (макеты, шаблоны, частичные реплики) в иерархическом порядке, начиная с той папки, где находится текущая страница. Макет в папке Pages/Shared можно использовать на любой странице Razor, которая находится в папке Pages.

            Файл макета следует поместить в папку Pages/Shared.

            Корпорация Майкрософт рекомендует не размещать файл макета в папке Views/Shared. Views/Shared — это шаблон представлений MVC. Razor Pages опирается на иерархию папок, а не на условные обозначения путей.

            Поиск представлений в Razor Pages охватывает папку Pages. Макеты, шаблоны и частичные реплики работают с контроллерами MVC и стандартными представлениями Razor.

            Добавьте файл Pages/_ViewImports.cshtml :

            @namespace RazorPagesContacts.Pages @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 

            @namespace описывается далее в этом руководстве. Директива @addTagHelper добавляет встроенные вспомогательные теги на все страницы в папке Pages.

            Директива @namespace , заданная на странице:

            @page @namespace RazorPagesIntro.Pages.Customers @model NameSpaceModel 

            Name space

            @Model.Message

            Директива @namespace задает пространство имен для страницы. Включать пространство имен в директиву @model не требуется.

            Если директива @namespace содержится в файле _ViewImports.cshtml , указанное пространство имен определяет префикс для созданного в Pages пространства имен, куда импортируется директива @namespace . Остальная часть созданного пространства имен (суффикс) представляет собой разделенный точками относительный путь между папкой с файлом _ViewImports.cshtml и папкой, содержащей страницу.

            Например, класс PageModel в файле Pages/Customers/Edit.cshtml.cs задает пространство имен явно:

            namespace RazorPagesContacts.Pages < public class EditModel : PageModel < private readonly AppDbContext _db; public EditModel(AppDbContext db) < _db = db; >// Code removed for brevity. 

            Файл Pages/_ViewImports.cshtml задает следующее пространство имен:

            @namespace RazorPagesContacts.Pages @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 

            Созданное пространство имен для файла Pages/Customers/Edit.cshtml Razor Pages совпадает с пространством имен класса PageModel .

            @namespace также работает со стандартными представлениями Razor.

            Изучите файл представления Pages/Customers/Create.cshtml :

            @page @model RazorPagesContacts.Pages.Customers.CreateModel @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 

            Validation: customer name:

            Name:

            Обновленный файл представления Pages/Customers/Create.cshtml с _ViewImports.cshtml и предыдущим файлом макета:

            @page @model CreateModel 

            Enter a customer name:

            Name:

            В приведенном выше коде _ViewImports.cshtml импортировал пространство имен и вспомогательные функции тегов. Файл макета импортировал файлы JavaScript.

            Начальный проект Razor Pages содержит Pages/_ValidationScriptsPartial.cshtml , который обеспечивает проверку со стороны клиента.

            Дополнительные сведения о частичных представлениях см. в статье Частичные представления в ASP.NET Core.

            Формирование URL-адресов для страниц

            На представленной выше странице Create используется RedirectToPage :

            public class CreateModel : PageModel < private readonly Data.CustomerDbContext _context; public CreateModel(Data.CustomerDbContext context) < _context = context; >public IActionResult OnGet() < return Page(); >[BindProperty] public Customer? Customer < get; set; >public async Task OnPostAsync() < if (!ModelState.IsValid) < return Page(); >if (Customer != null) _context.Customer.Add(Customer); await _context.SaveChangesAsync(); return RedirectToPage("./Index"); > > 

            Это приложение имеет следующую структуру файлов и папок:

            • Pages/
              • Index.cshtml
              • Privacy.cshtml
              • /Customers
                • Create.cshtml
                • Edit.cshtml
                • Index.cshtml

                Страницы Pages/Customers/Create.cshtml и Pages/Customers/Edit.cshtml перенаправляются в Pages/Customers/Index.cshtml после выполнения. Строка ./Index — это относительное имя страницы, используемое для доступа к предыдущей странице. Он используется для создания URL-адресов страницы Pages/Customers/Index.cshtml . Например:

                • Url.Page("./Index", . )
                • Customers Index Page
                • RedirectToPage("./Index")

                С помощью абсолютного имени страницы /Index создаются URL-адреса страницы Pages/Index.cshtml . Например:

                • Url.Page("/Index", . )
                • Home Index Page
                • RedirectToPage("/Index")

                Имя страницы — это путь к странице из корневой папки /Pages, включая начальный символ / (например, /Index ). Предыдущие образцы создания URL-адреса обеспечивают расширенные параметры и функциональные возможности по сравнению с жестким заданием URL-адреса. Формирование URL-адресов включает маршрутизацию и позволяет генерировать и включать в код параметры в зависимости от того, как определяется маршрут в пути назначения.

                Формирование URL-адресов для страниц поддерживает относительные имена. В приведенной ниже таблице показано, какая страница индекса выбирается с помощью разных параметров RedirectToPage в Pages/Customers/Create.cshtml .

                RedirectToPage(x) Страница
                RedirectToPage("/Index") Pages/Index
                RedirectToPage("./Index"); Pages/Customers/Index
                RedirectToPage("../Index") Pages/Index
                RedirectToPage("Index") Pages/Customers/Index

                RedirectToPage("Index") , RedirectToPage("./Index") и RedirectToPage("../Index") — это относительные имена. Для получения имени целевой страницы параметр RedirectToPage комбинируется с путем текущей страницы.

                Привязка относительных имен полезна при создании сайтов со сложной структурой. Если относительные имена используются для связи между страницами в папке:

                • Переименование папки не нарушает относительные ссылки.
                • Ссылки не нарушаются, так как не содержат имя папки.

                Чтобы выполнить перенаправление на страницу в другой области, укажите эту область:

                RedirectToPage("/Index", new < area = "Services" >); 

                Атрибут ViewData

                Данные могут передаваться на страницу с помощью атрибута ViewDataAttribute. Значения свойств с атрибутом [ViewData] хранятся в ViewDataDictionary и загружаются из него.

                В следующем примере AboutModel применяет атрибут [ViewData] к свойству Title :

                public class AboutModel : PageModel < [ViewData] public string Title < get; >= "About"; public void OnGet() < >> 

                На странице About доступ к свойству Title осуществляется как доступ к свойству модели.

                @Model.Title

                В макете заголовок считывается из словаря ViewData.

                   @ViewData["Title"] - WebApplication . 

                TempData

                ASP.NET Core предоставляет TempData. Это свойство хранит данные до тех пор, пока они не будут прочитаны. Для проверки данных без удаления можно использовать методы Keep и Peek. TempData удобно использовать для перенаправления, когда данные требуются больше, чем для одного запроса.

                В следующем коде значение Message задается с помощью TempData :

                public class CreateDotModel : PageModel < private readonly AppDbContext _db; public CreateDotModel(AppDbContext db) < _db = db; >[TempData] public string Message < get; set; >[BindProperty] public Customer Customer < get; set; >public async Task OnPostAsync() < if (!ModelState.IsValid) < return Page(); >_db.Customers.Add(Customer); await _db.SaveChangesAsync(); Message = $"Customer added"; return RedirectToPage("./Index"); > > 

                Представленная ниже разметка в файле Pages/Customers/Index.cshtml отображает значение Message с помощью TempData .

                Msg: @Model.Message

                Модель страницы Pages/Customers/Index.cshtml.cs применяет атрибут [TempData] ко свойству Message .

                [TempData] public string Message

                Дополнительные сведения см. в разделе TempData.

                Несколько обработчиков на страницу

                Следующая страница формирует разметку для двух обработчиков с помощью вспомогательной функции тегов asp-page-handler :

                @page @model CreateFATHModel   

                Enter your name.

                Name:
                --> -->

                Форма в предыдущем примере включает две кнопки отправки, каждая из которых отправляет данные на отдельный URL-адрес с помощью FormActionTagHelper . Атрибут asp-page-handler является дополнением к asp-page . Атрибут asp-page-handler формирует URL-адреса, ,которые используются для отправки данных в каждый из методов обработчиков, определенных страницей. asp-page не задается, так как пример сопоставлен с текущей страницей.

                using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; using RazorPagesContacts.Data; namespace RazorPagesContacts.Pages.Customers < public class CreateFATHModel : PageModel < private readonly AppDbContext _db; public CreateFATHModel(AppDbContext db) < _db = db; >[BindProperty] public Customer Customer < get; set; >public async Task OnPostJoinListAsync() < if (!ModelState.IsValid) < return Page(); >_db.Customers.Add(Customer); await _db.SaveChangesAsync(); return RedirectToPage("/Index"); > public async Task OnPostJoinListUCAsync() < if (!ModelState.IsValid) < return Page(); >Customer.Name = Customer.Name?.ToUpperInvariant(); return await OnPostJoinListAsync(); > > > 

                В представленном выше коде используются именованные методы обработчика. Именованные методы обработчика создаются путем размещения определенного текста в имени после On и перед Async (если есть). В приведенном выше примере использовались методы страницы OnPostJoinListAsync и OnPostJoinListUCAsync. Если убрать OnPost и Async, имена обработчиков будут выглядеть как JoinList и JoinListUC .

                При использовании представленного выше кода URL-путь для отправки данных в OnPostJoinListAsync будет выглядеть как https://localhost:5001/Customers/CreateFATH?handler=JoinList . URL-путь для отправки данных в OnPostJoinListUCAsync будет иметь вид https://localhost:5001/Customers/CreateFATH?handler=JoinListUC .

                Пользовательские маршруты

                С помощью директивы @page можно сделать следующее.

                • Указать пользовательский маршрут к странице. Например, можно задать маршрут к странице "Сведения" /Some/Other/Path : @page "/Some/Other/Path" .
                • Добавить сегменты к маршруту страницы по умолчанию. Например, к такому маршруту можно добавить сегмент item: @page "item" .
                • Добавить параметры к маршруту страницы по умолчанию. Например, для страницы с @page "" может потребоваться параметр идентификатора id .

                Поддерживается путь относительно корня, заданный знаком тильды ( ~ ) в начале пути. Например, @page "~/Some/Other/Path" — это тоже самое, что и @page "/Some/Other/Path" .

                Если вы не хотите, чтобы в URL-адресе отображалась строка запроса ?handler=JoinList , измените маршрут так, чтобы в качестве пути в URL-адресе указывалось имя обработчика. Для настройки маршрута добавьте после директивы @page шаблон маршрута, заключенный в двойные кавычки.

                @page "" @model CreateRouteModel   

                Enter your name.

                Name:

                При использовании представленного выше кода URL-путь для отправки данных в OnPostJoinListAsync будет выглядеть как https://localhost:5001/Customers/CreateFATH/JoinList . URL-путь для отправки данных в OnPostJoinListUCAsync будет иметь вид https://localhost:5001/Customers/CreateFATH/JoinListUC .

                Символ ? после handler означает, что параметр маршрута является необязательным.

                Совместное размещение файлов JavaScript (JS)

                Совместное размещение файлов JavaScriptJS для страниц и представлений — удобный способ упорядочивания скриптов в приложении.

                Совместное размещение файлов JS с использованием следующих соглашений о расширении имен файлов:

                • Страницы приложений Razor Pages и представления приложений MVC: .cshtml.js . Примеры:
                  • Pages/Index.cshtml.js для страницы Index приложения Razor Pages в Pages/Index.cshtml .
                  • Views/Home/Index.cshtml.js для представления Index приложения MVC в Views/Home/Index.cshtml .

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

                  • Страницы и представления из файла скриптов с сортировкой в приложении: /..js
                    • Заполнитель — это путь к странице, представлению или компоненту.
                    • Заполнитель — это страница, представление или компонент.
                    • Заполнитель соответствует расширению страницы, представления или компонента, либо razor или cshtml .

                    Пример Razor Pages:

                    Файл JS для страницы Index помещается в папку Pages ( Pages/Index.cshtml.js ) рядом со страницей Index ( Pages/Index.cshtml ). На странице Index на скрипт указана ссылка по пути в папке Pages :

                    @section Scripts <  > 

                    При публикации приложения платформа автоматически перемещает скрипт в корневой каталог. В предыдущем примере скрипт перемещается в bin\Release\\publish\wwwroot\Pages\Index.cshtml.js , где заполнитель замещен моникером целевой платформы (TFM). Относительный URL-адрес скрипта на странице Index изменять не нужно.

                    При публикации приложения платформа автоматически перемещает скрипт в корневой каталог. В предыдущем примере скрипт перемещается в bin\Release\\publish\wwwroot\Components\Pages\Index.razor.js , где заполнитель замещен моникером целевой платформы (TFM). Относительный URL-адрес скрипта в компоненте Index изменять не нужно.

                    • Заполнитель — это идентификатор пакета RCL (или имя библиотеки для библиотеки классов, на которую ссылается приложение).
                    • Заполнитель — это путь к странице, представлению или компоненту. Если компонент Razor находится в корне RCL, сегмент пути не включается.
                    • Заполнитель — это страница, представление или компонент.
                    • Заполнитель соответствует расширению страницы, представления или компонента, либо razor или cshtml .

                    Расширенная конфигурация и параметры

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

                    Для настройки расширенных параметров используйте перегрузку AddRazorPages, которая настраивает RazorPagesOptions:

                    using Microsoft.EntityFrameworkCore; using RazorPagesContacts.Data; var builder = WebApplication.CreateBuilder(args); builder.Services.AddRazorPages(options => < options.RootDirectory = "/MyPages"; options.Conventions.AuthorizeFolder("/MyPages/Admin"); >); builder.Services.AddDbContext(options => options.UseInMemoryDatabase("name")); var app = builder.Build(); if (!app.Environment.IsDevelopment()) < app.UseExceptionHandler("/Error"); app.UseHsts(); >app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.UseAuthorization(); app.MapRazorPages(); app.Run(); 

                    Используйте RazorPagesOptions, чтобы задавать корневой каталог для страниц и добавлять для них соглашения моделей приложений. Дополнительные сведения о соглашениях см. в разделе Соглашения об авторизации Razor Pages.

                    Сведения о предварительной компиляции представлений см. на странице Компиляция представлений Razor.

                    Указание местонахождения Razor Pages в корне каталога

                    По умолчанию Razor Pages находится в корне каталога /Pages. Добавьте WithRazorPagesAtContentRoot, чтобы указать, что Razor Pages находится в корневой папке содержимого (ContentRootPath) приложения:

                    using Microsoft.EntityFrameworkCore; using RazorPagesContacts.Data; var builder = WebApplication.CreateBuilder(args); builder.Services.AddRazorPages(options => < options.Conventions.AuthorizeFolder("/MyPages/Admin"); >) .WithRazorPagesAtContentRoot(); builder.Services.AddDbContext(options => options.UseInMemoryDatabase("name")); var app = builder.Build(); if (!app.Environment.IsDevelopment()) < app.UseExceptionHandler("/Error"); app.UseHsts(); >app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.UseAuthorization(); app.MapRazorPages(); app.Run(); 

                    Указание местонахождения Razor Pages в пользовательском корневом каталоге

                    Добавьте WithRazorPagesRoot, чтобы указать, что Razor Pages находится в пользовательском корневом каталоге в приложении (укажите относительный путь):

                    using Microsoft.EntityFrameworkCore; using RazorPagesContacts.Data; var builder = WebApplication.CreateBuilder(args); builder.Services.AddRazorPages(options => < options.Conventions.AuthorizeFolder("/MyPages/Admin"); >) .WithRazorPagesRoot("/path/to/razor/pages"); builder.Services.AddDbContext(options => options.UseInMemoryDatabase("name")); var app = builder.Build(); if (!app.Environment.IsDevelopment()) < app.UseExceptionHandler("/Error"); app.UseHsts(); >app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.UseAuthorization(); app.MapRazorPages(); app.Run(); 

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

                    • Дополнительные общие сведения см. на странице Учебник. Начало работы с Razor Pages в ASP.NET Core.
                    • Атрибут authorize и Razor Pages
                    • Загрузить или просмотреть пример кода.
                    • Общие сведения об ASP.NET Core
                    • Справочник по синтаксису Razor для ASP.NET Core
                    • Области в ASP.NET Core
                    • Учебник. Начало работы с Razor Pages в ASP.NET Core
                    • Соглашения об авторизации Razor Pages в ASP.NET Core
                    • Соглашения для маршрутов и приложений Razor Pages в ASP.NET Core
                    • Модульные тесты Razor Pages в ASP.NET Core
                    • Частичные представления в ASP.NET Core
                    • Visual Studio
                    • Visual Studio Code
                    • Visual Studio для Mac
                    • Visual Studio 2019 16.4 или более поздней версии с рабочей нагрузкой ASP.NET и разработка веб-приложений
                    • Пакет SDK для .NET Core 3.1
                    • Visual Studio Code
                    • C# для Visual Studio Code (последняя версия)
                    • Пакет SDK для .NET Core 3.1

                    Для функций разработки ASP.NET Core, таких как создание проекта, в инструкциях Visual Studio Code используется .NET Core CLI. Эти инструкции можно выполнять на любой платформе (macOS, Linux или Windows) и в любом редакторе кода. При использовании редактора, отличного от Visual Studio Code, может потребоваться внести незначительные изменения. Дополнительные сведения об установке Visual Studio Code в macOS см. в статье Visual Studio Code в macOS.

                    • Visual Studio для Mac 8.4 или более поздней версии
                    • Пакет SDK для .NET Core 3.1
                    • Visual Studio
                    • Visual Studio Code
                    • Visual Studio для Mac
                    • Visual Studio 2019 16.8 или более поздней версии с рабочей нагрузкой ASP.NET и разработка веб-приложений
                    • Пакет SDK для .NET 5.0
                    • Visual Studio Code
                    • C# для Visual Studio Code (последняя версия)
                    • Пакет SDK для .NET 5.0

                    Для функций разработки ASP.NET Core, таких как создание проекта, в инструкциях Visual Studio Code используется .NET CLI. Эти инструкции можно выполнять на macOS, Linux или Windows и в любом редакторе кода. При использовании редактора, отличного от Visual Studio Code, может потребоваться внести незначительные изменения.

                    • Visual Studio для Mac
                    • Пакет SDK для .NET 5.0

                    Создание проекта Razor Pages

                    • Visual Studio
                    • Visual Studio Code
                    • Visual Studio для Mac

                    Подробные инструкции по созданию проекта Razor Pages см. в статье Начало работы с Razor Pages.

                    Из командной строки выполните команду dotnet new webapp .

                    Подробные инструкции по созданию проекта Razor Pages см. в статье Начало работы с Razor Pages.

                    Razor Pages

                    Razor Страницы включены в Startup.cs :

                    public class Startup < public Startup(IConfiguration configuration) < Configuration = configuration; >public IConfiguration Configuration < get; >public void ConfigureServices(IServiceCollection services) < services.AddRazorPages(); >public void Configure(IApplicationBuilder app, IWebHostEnvironment env) < if (env.IsDevelopment()) < app.UseDeveloperExceptionPage(); >else < app.UseExceptionHandler("/Error"); app.UseHsts(); >app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.UseAuthorization(); app.UseEndpoints(endpoints => < endpoints.MapRazorPages(); >); > > 

                    Рассмотрим простую страницу:

                    @page 

                    Hello, world!

                    The time on the server is @DateTime.Now

                    Приведенный выше код выглядит как Razor файл представления, используемый в приложениях ASP.NET Core с контроллерами и представлениями. Он отличается от него только директивой @page . Директива @page превращает файл в действие MVC, а значит обрабатывает запросы напрямую, минуя контроллер. @page должна быть первой директивой Razor на странице. @page влияет на поведение всех остальных конструкций Razor. Имена файлов Razor Pages содержат суффикс .cshtml .

                    Похожая страница с использованием класса PageModel показана в следующих двух файлах. Файл Pages/Index2.cshtml :

                    @page @using RazorPagesIntro.Pages @model Index2Model 

                    Separate page model

                    @Model.Message

                    Модель страницы Pages/Index2.cshtml.cs :

                    using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.Extensions.Logging; using System; namespace RazorPagesIntro.Pages < public class Index2Model : PageModel < public string Message < get; private set; >= "PageModel in C#"; public void OnGet() < Message += $" Server time is < DateTime.Now >"; > > > 

                    По соглашению файл класса имеет то же имя, PageModel что Razor и файл page с .cs добавленным. Например, предыдущая страница Razor Pages называется Pages/Index2.cshtml . Файл, содержащий класс PageModel , называется Pages/Index2.cshtml.cs .

                    Сопоставления URL-адресов со страницами определяются расположением конкретной страницы в файловой системе. В приведенной ниже таблице показаны пути Razor Pages и соответствующие URL-адреса.

                    Имя файла и путь Соответствующий URL
                    /Pages/Index.cshtml / или /Index
                    /Pages/Contact.cshtml /Contact
                    /Pages/Store/Contact.cshtml /Store/Contact
                    /Pages/Store/Index.cshtml /Store или /Store/Index
                    • Среда выполнения по умолчанию ищет файлы Razor Pages в папке Pages.
                    • Если в URL-адресе не указана конкретная страница, по умолчанию открывается страница Index .

                    Создание простой формы

                    Razor Pages предназначена для упрощения реализации типовых шаблонов, которые используются в браузерах, при создании приложения. Привязки модели, вспомогательные функции тегов и вспомогательные методы HTML отлично работают со свойствами, определенными в классе Razor Pages. Рассмотрим страницу с простой формой связи для модели Contact .

                    В представленных в этой статье примерах DbContext инициализируется в файле Startup.cs.

                    Для работы с базой данных в памяти требуется пакет NuGet Microsoft.EntityFrameworkCore.InMemory .

                    public void ConfigureServices(IServiceCollection services) < services.AddDbContext(options => options.UseInMemoryDatabase("name")); services.AddRazorPages(); > 
                    using System.ComponentModel.DataAnnotations; namespace RazorPagesContacts.Models < public class Customer < public int Id < get; set; >[Required, StringLength(10)] public string Name < get; set; >> > 

                    Контекст базы данных:

                    using Microsoft.EntityFrameworkCore; using RazorPagesContacts.Models; namespace RazorPagesContacts.Data < public class CustomerDbContext : DbContext < public CustomerDbContext(DbContextOptions options) : base(options) < >public DbSet Customers < get; set; >> > 

                    Файл представления Pages/Create.cshtml :

                    @page @model RazorPagesContacts.Pages.Customers.CreateModel @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 

                    Enter a customer name:

                    Name:

                    Модель страницы Pages/Create.cshtml.cs :

                    using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; using RazorPagesContacts.Data; using RazorPagesContacts.Models; using System.Threading.Tasks; namespace RazorPagesContacts.Pages.Customers < public class CreateModel : PageModel < private readonly CustomerDbContext _context; public CreateModel(CustomerDbContext context) < _context = context; >public IActionResult OnGet() < return Page(); >[BindProperty] public Customer Customer < get; set; >public async Task OnPostAsync() < if (!ModelState.IsValid) < return Page(); >_context.Customers.Add(Customer); await _context.SaveChangesAsync(); return RedirectToPage("./Index"); > > > 

                    Как правило, класс PageModel называется Model и находится в том же пространстве имен, что и страница.

                    Класс PageModel позволяет разделять логику страницы и ее представление. Он определяет обработчики страницы для запросов, отправляемых на страницу, а также данные для ее визуализации. Это разделение позволяет:

                    • управлять зависимостями страниц с помощью внедрения зависимостей.
                    • Модульное тестирование

                    Страница содержит метод обработчика OnPostAsync , который выполняется по запросам POST (когда пользователь публикует форму). Можно добавить методы обработчика для любой HTTP-команды. Ниже перечислены наиболее распространенные обработчики.

                    • OnGet инициализирует нужное состояние для страницы. В приведенном выше коде метод OnGet отображает страницу Razor CreateModel.cshtml .
                    • OnPost обрабатывает отправку формы.

                    Суффикс имени Async является необязательным, но часто применяется в соответствии с соглашением для асинхронных функций. Этот код типичен для Razor Pages.

                    Если вы знакомы с приложениями ASP.NET, использующими контроллеры и представления:

                    • Код OnPostAsync в предыдущем примере похож на стандартный код контроллера.
                    • Большинство примитивов MVC, включая привязку модели, проверку и результаты действий, одинаково работают с контроллерами и Razor Pages.

                    Предыдущий метод OnPostAsync :

                    public async Task OnPostAsync() < if (!ModelState.IsValid) < return Page(); >_context.Customers.Add(Customer); await _context.SaveChangesAsync(); return RedirectToPage("./Index"); > 

                    Простая схема OnPostAsync :

                    Проверка на наличие ошибок проверки.

                    • Если ошибок нет, сохранение данных и перенаправление.
                    • Если есть ошибки, отображение страницы с сообщениями проверки. Зачастую ошибки выявляются при проверке в клиенте и не передаются на сервер.

                    Файл представления Pages/Create.cshtml :

                    @page @model RazorPagesContacts.Pages.Customers.CreateModel @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 

                    Enter a customer name:

                    Name:

                    Отрисованный HTML из Pages/Create.cshtml :

                    Enter a customer name:

                    Name: " />

                    В приведенном выше коде, разместив форму:

                    • С допустимыми данными:
                      • Метод обработчика OnPostAsync вызывает вспомогательный метод RedirectToPage. RedirectToPage возвращает экземпляр RedirectToPageResult. RedirectToPage :
                        • Является результатом действия.
                        • Аналогичен RedirectToAction или RedirectToRoute (используется в контроллерах и представлениях).
                        • Настраивается для страниц. В приведенном выше примере он выполняет перенаправление на корневую страницу индекса ( /Index ). Более подробно RedirectToPage рассматривается в разделе Создание URL для страниц.
                        • Метод обработчика OnPostAsync вызывает вспомогательный метод Page. Page возвращает экземпляр PageResult. Возвращение Page аналогично тому, как действия в контроллерах возвращают View . PageResult — тип возвращаемого значения по умолчанию для метода обработчика. Метод обработчика, вернувший void , визуализирует страницу.
                        • В предыдущем примере публикация формы без значения приводит к тому, что ModelState.IsValid возвращает значение false. В этом примере на клиенте не отображаются ошибки проверки. Обработка ошибок проверки рассматривается далее в этом документе.
                        public async Task OnPostAsync() < if (!ModelState.IsValid) < return Page(); >_context.Customers.Add(Customer); await _context.SaveChangesAsync(); return RedirectToPage("./Index"); > 
                        • Данные не отправляются на сервер.
                        • Проверка на стороне клиента описана далее в этом документе.

                        Для указания согласия на привязку модели в свойстве Customer используется атрибут [BindProperty] :

                        public class CreateModel : PageModel < private readonly CustomerDbContext _context; public CreateModel(CustomerDbContext context) < _context = context; >public IActionResult OnGet() < return Page(); >[BindProperty] public Customer Customer < get; set; >public async Task OnPostAsync() < if (!ModelState.IsValid) < return Page(); >_context.Customers.Add(Customer); await _context.SaveChangesAsync(); return RedirectToPage("./Index"); > > 

                        [BindProperty] не следует использовать в моделях, содержащих свойства, которые не должны изменяться клиентом. Дополнительные сведения см. в этом разделе.

                        По умолчанию Razor привязывает свойства ко всем командам, кроме GET . Привязка к свойствам устраняет необходимость в написании кода для преобразования данных HTTP в тип модели. Привязка уменьшает код за счет того, что для визуализации полей формы ( ) и получения входных данных используется одно и то же свойство.

                        В целях безопасности вам следует задать привязку данных запроса GET к свойствам страничной модели. Проверьте введенные данные пользователя, прежде чем сопоставлять их со свойствами. Привязка GET полезна при обращении к сценариям, использующим строку запроса или значения маршрутов.

                        Чтобы привязать свойство к запросам GET , задайте для свойства SupportsGet атрибута [BindProperty] значение true :

                        [BindProperty(SupportsGet = true)] 

                        Pages/Create.cshtml Просмотр файла представления:

                        @page @model RazorPagesContacts.Pages.Customers.CreateModel @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 

                        Enter a customer name:

                        Name:
                        • В приведенном выше коде вспомогательная функция тега вводапривязывает элемент HTML к выражению модели Customer.Name .
                        • Директива @addTagHelper обеспечивает доступность вспомогательных функций тегов.

                        Домашняя страница.

                        Index.cshtml является домашней страницей:

                        @page @model RazorPagesContacts.Pages.Customers.IndexModel @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 

                        Contacts home page

                        @foreach (var contact in Model.Customer) < >
                        ID Name
                        @contact.Id @contact.Name --> Edit | --> --> -->
                        Create New

                        Связанный класс PageModel ( Index.cshtml.cs ):

                        public class IndexModel : PageModel < private readonly CustomerDbContext _context; public IndexModel(CustomerDbContext context) < _context = context; >public IList Customer < get; set; >public async Task OnGetAsync() < Customer = await _context.Customers.ToListAsync(); >public async Task OnPostDeleteAsync(int id) < var contact = await _context.Customers.FindAsync(id); if (contact != null) < _context.Customers.Remove(contact); await _context.SaveChangesAsync(); >return RedirectToPage(); > > 

                        Файл Index.cshtml содержит следующую разметку:

                        Вспомогательный тег привязки использовал атрибут asp-route- для создания ссылки на страницу редактирования. Эта ссылка содержит данные о маршруте с идентификатором контактного лица. Например, https://localhost:5001/Edit/1 . Вспомогательные функции тегов позволяют серверному коду участвовать в создании и отображении HTML-элементов в файлах Razor.

                        Файл Index.cshtml содержит разметку для создания кнопки удаления для каждого контакта клиента:

                         
                         

                        Во время обработки кнопки удаления в HTML ее formaction включает параметры для следующего:

                        • Идентификатор контакта клиента, указанный атрибутом asp-route-id .
                        • Параметр handler , указанный атрибутом asp-page-handler .

                        При выборе кнопки на сервер отправляется запрос формы POST . По соглашению имя метода обработчика выбирается на основе значения параметра handler в соответствии со схемой OnPost[handler]Async .

                        Так как handler — delete в этом примере, метод обработчика OnPostDeleteAsync используется для обработки запроса POST . Если asp-page-handler имеет другое значение, например remove , выбирается метод обработчика с именем OnPostRemoveAsync .

                        public async Task OnPostDeleteAsync(int id) < var contact = await _context.Customers.FindAsync(id); if (contact != null) < _context.Customers.Remove(contact); await _context.SaveChangesAsync(); >return RedirectToPage(); > 
                        • Получает id из строки запроса.
                        • Отправляет в базу данных запрос контакта клиента с FindAsync .
                        • Если контакт клиента найден, он удаляется, и база данных обновляется.
                        • Вызывает RedirectToPage для перенаправления на корневую страницу индекса ( /Index ).

                        Файл Edit.cshtml

                        @page "" @model RazorPagesContacts.Pages.Customers.EditModel @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 

                        Edit Customer - @Model.Customer.Id

                        Первая строка содержит директиву @page "" . Ограничение маршрутизации "" указывает, что страница должна принимать обращенные к ней запросы, которые содержат данные маршрутизации int . Если запрос к странице не содержит данные о маршруте, которые можно конвертировать в int , среда выполнения возвращает ошибку HTTP 404 (не найдено). Чтобы сделать идентификатор необязательным, добавьте ? к ограничению маршрута:

                        @page "" 
                        public class EditModel : PageModel < private readonly CustomerDbContext _context; public EditModel(CustomerDbContext context) < _context = context; >[BindProperty] public Customer Customer < get; set; >public async Task OnGetAsync(int id) < Customer = await _context.Customers.FindAsync(id); if (Customer == null) < return RedirectToPage("./Index"); >return Page(); > public async Task OnPostAsync() < if (!ModelState.IsValid) < return Page(); >_context.Attach(Customer).State = EntityState.Modified; try < await _context.SaveChangesAsync(); >catch (DbUpdateConcurrencyException) < throw new Exception($"Customer not found!"); > return RedirectToPage("./Index"); > > 

                        Проверка

                        • Декларативно задаются в классе Model.
                        • Применяются везде в приложении.

                        Пространство имен System.ComponentModel.DataAnnotations предоставляет набор встроенных атрибутов проверки, которые декларативно применяются к классу или свойству. Кроме того, DataAnnotations содержит атрибуты форматирования (такие как [DataType] ), которые обеспечивают форматирование и не предназначены для проверки.

                        Рассмотрим модель Customer :

                        using System.ComponentModel.DataAnnotations; namespace RazorPagesContacts.Models < public class Customer < public int Id < get; set; >[Required, StringLength(10)] public string Name < get; set; >> > 

                        С помощью следующего Create.cshtml файла представления:

                        @page @model RazorPagesContacts.Pages.Customers.CreateModel @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 

                        Validation: customer name:

                        Name:
                        • Включает jQuery и скрипты проверки jQuery.
                        • Использует вспомогательные функции тегови для включения следующего:
                          • Проверка на стороне клиента.
                          • Отображение ошибок при проверке.

                          Enter a customer name:

                          Name: " />

                          При публикации формы создания без значения имени в форме отображается сообщение об ошибке: "Поле имени является обязательным". Если на клиенте включен JavaScript, браузер отображает ошибку без отправки на сервер.

                          Атрибут [StringLength(10)] создает data-val-length-max="10" в отображаемом HTML-коде. data-val-length-max не дает браузерам ввести больше заданной максимальной длины. Если для изменения и воспроизведения записи используется средство, например Fiddler, выполните следующие действия:

                          • С именем, превышающим 10.
                          • Возвращается сообщение об ошибке: "Имя поля должно быть строкой с максимальной длиной 10".

                          Рассмотрим следующую модель Movie :

                          using System; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; namespace RazorPagesMovie.Models < public class Movie < public int ID < get; set; >[StringLength(60, MinimumLength = 3)] [Required] public string Title < get; set; >[Display(Name = "Release Date")] [DataType(DataType.Date)] public DateTime ReleaseDate < get; set; >[Range(1, 100)] [DataType(DataType.Currency)] [Column(TypeName = "decimal(18, 2)")] public decimal Price < get; set; >[RegularExpression(@"^[A-Z]+[a-zA-Z\s]*$")] [Required] [StringLength(30)] public string Genre < get; set; >[RegularExpression(@"^[A-Z]+[a-zA-Z0-9""'\s-]*$")] [StringLength(5)] [Required] public string Rating < get; set; >> > 

                          Атрибуты проверки определяют поведение для свойств модели, к которым они применяются:

                          • Атрибуты Required и MinimumLength указывают, что свойство должно иметь значение. Тем не менее, чтобы удовлетворить требованиям проверки, пользователю достаточно ввести пробел.
                          • Атрибут RegularExpression ограничивает набор допустимых для ввода символов. В приведенном выше коде в Genre:
                            • должны использоваться только буквы;
                            • первая буква должна быть прописной; пробелы, цифры и специальные символы не допускаются.
                            • первый символ должен быть прописной буквой;
                            • допускаются специальные символы и цифры, а также последующие пробелы. Значение "PG-13" допустимо для рейтинга, но недопустимо для жанра.

                            На странице создания для модели Movie отображаются ошибки с недопустимыми значениями:

                            Movie view form with multiple jQuery client-side validation errors

                            Дополнительные сведения см. в разделе:

                            • Добавление проверки в приложение Movie
                            • Проверка модели в ASP.NET Core.

                            Обработка запросов HEAD с помощью вызова резервного обработчика OnGet

                            Запросы HEAD позволяют получать заголовки для определенного ресурса. В отличие от запросов GET запросы HEAD не возвращают текст ответа.

                            Обработчик OnHead обычно создается и вызывается для выполнения запросов HEAD :

                            public void OnHead()

                            Если обработчик OnHead не определен, Razor Pages выполнит вызов обработчика OnGet .

                            XSRF/CSRF и Razor Pages

                            В Razor Pages реализована проверка для защиты от подделки. FormTagHelper вставляет маркеры защиты от подделки в элементы HTML-форм.

                            Использование макетов, частичных реплик, шаблонов и вспомогательных функций тегов с Razor Pages

                            Pages работает со всеми функциями подсистемы просмотра Razor. Макеты, частичные реплики, шаблоны, вспомогательные функции тегов, _ViewStart.cshtml и _ViewImports.cshtml одинаково работают для обычных представлений Razor.

                            Давайте упростим нашу страницу с помощью некоторых из этих функций.

                            Добавьте страницу макета в Pages/Shared/_Layout.cshtml :

                               RP Sample  Home Create Customers 
                            @RenderBody()
                            • управляет макетом каждой страницы (кроме страниц с отказом от макета);
                            • импортирует HTML-структуры, такие как JavaScript и таблицы стилей.
                            • Содержимое страницы Razor отображается в том месте, где вызывается @RenderBody() .

                            Дополнительные сведения см. здесь.

                            Свойство макета задается в Pages/_ViewStart.cshtml :

                            Макет хранится в папке Pages/Shared. Pages ищет другие представления (макеты, шаблоны, частичные реплики) в иерархическом порядке, начиная с той папки, где находится текущая страница. Макет в папке Pages/Shared можно использовать на любой странице Razor, которая находится в папке Pages.

                            Файл макета следует поместить в папку Pages/Shared.

                            Корпорация Майкрософт рекомендует не размещать файл макета в папке Views/Shared. Views/Shared — это шаблон представлений MVC. Razor Pages опирается на иерархию папок, а не на условные обозначения путей.

                            Поиск представлений в Razor Pages охватывает папку Pages. Макеты, шаблоны и частичные реплики работают с контроллерами MVC и стандартными представлениями Razor.

                            Добавьте файл Pages/_ViewImports.cshtml :

                            @namespace RazorPagesContacts.Pages @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 

                            @namespace описывается далее в этом руководстве. Директива @addTagHelper добавляет встроенные вспомогательные теги на все страницы в папке Pages.

                            Директива @namespace , заданная на странице:

                            @page @namespace RazorPagesIntro.Pages.Customers @model NameSpaceModel 

                            Name space

                            @Model.Message

                            Директива @namespace задает пространство имен для страницы. Включать пространство имен в директиву @model не требуется.

                            Если директива @namespace содержится в файле _ViewImports.cshtml , указанное пространство имен определяет префикс для созданного в Pages пространства имен, куда импортируется директива @namespace . Остальная часть созданного пространства имен (суффикс) представляет собой разделенный точками относительный путь между папкой с файлом _ViewImports.cshtml и папкой, содержащей страницу.

                            Например, класс PageModel в файле Pages/Customers/Edit.cshtml.cs задает пространство имен явно:

                            namespace RazorPagesContacts.Pages < public class EditModel : PageModel < private readonly AppDbContext _db; public EditModel(AppDbContext db) < _db = db; >// Code removed for brevity. 

                            Файл Pages/_ViewImports.cshtml задает следующее пространство имен:

                            @namespace RazorPagesContacts.Pages @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 

                            Созданное пространство имен для файла Pages/Customers/Edit.cshtml Razor Pages совпадает с пространством имен класса PageModel .

                            @namespace также работает со стандартными представлениями Razor.

                            Изучите файл представления Pages/Create.cshtml :

                            @page @model RazorPagesContacts.Pages.Customers.CreateModel @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 

                            Validation: customer name:

                            Name:

                            Обновленный файл представления Pages/Create.cshtml с _ViewImports.cshtml и предыдущим файлом макета:

                            @page @model CreateModel 

                            Enter a customer name:

                            Name:

                            В приведенном выше коде _ViewImports.cshtml импортировал пространство имен и вспомогательные функции тегов. Файл макета импортировал файлы JavaScript.

                            Начальный проект Razor Pages содержит Pages/_ValidationScriptsPartial.cshtml , который обеспечивает проверку со стороны клиента.

                            Дополнительные сведения о частичных представлениях см. в статье Частичные представления в ASP.NET Core.

                            Формирование URL-адресов для страниц

                            На представленной выше странице Create используется RedirectToPage :

                            public class CreateModel : PageModel < private readonly CustomerDbContext _context; public CreateModel(CustomerDbContext context) < _context = context; >public IActionResult OnGet() < return Page(); >[BindProperty] public Customer Customer < get; set; >public async Task OnPostAsync() < if (!ModelState.IsValid) < return Page(); >_context.Customers.Add(Customer); await _context.SaveChangesAsync(); return RedirectToPage("./Index"); > > 

                            Это приложение имеет следующую структуру файлов и папок:

                            • Pages/
                              • Index.cshtml
                              • Privacy.cshtml
                              • /Customers
                                • Create.cshtml
                                • Edit.cshtml
                                • Index.cshtml

                                Страницы Pages/Customers/Create.cshtml и Pages/Customers/Edit.cshtml перенаправляются в Pages/Customers/Index.cshtml после выполнения. Строка ./Index — это относительное имя страницы, используемое для доступа к предыдущей странице. Он используется для создания URL-адресов страницы Pages/Customers/Index.cshtml . Например:

                                • Url.Page("./Index", . )
                                • Customers Index Page
                                • RedirectToPage("./Index")

                                С помощью абсолютного имени страницы /Index создаются URL-адреса страницы Pages/Index.cshtml . Например:

                                • Url.Page("/Index", . )
                                • Home Index Page
                                • RedirectToPage("/Index")

                                Имя страницы — это путь к странице из корневой папки /Pages, включая начальный символ / (например, /Index ). Предыдущие образцы создания URL-адреса обеспечивают расширенные параметры и функциональные возможности по сравнению с жестким заданием URL-адреса. Формирование URL-адресов включает маршрутизацию и позволяет генерировать и включать в код параметры в зависимости от того, как определяется маршрут в пути назначения.

                                Формирование URL-адресов для страниц поддерживает относительные имена. В приведенной ниже таблице показано, какая страница индекса выбирается с помощью разных параметров RedirectToPage в Pages/Customers/Create.cshtml .

                                RedirectToPage(x) Страница
                                RedirectToPage("/Index") Pages/Index
                                RedirectToPage("./Index"); Pages/Customers/Index
                                RedirectToPage("../Index") Pages/Index
                                RedirectToPage("Index") Pages/Customers/Index

                                RedirectToPage("Index") , RedirectToPage("./Index") и RedirectToPage("../Index") — это относительные имена. Для получения имени целевой страницы параметр RedirectToPage комбинируется с путем текущей страницы.

                                Привязка относительных имен полезна при создании сайтов со сложной структурой. Если относительные имена используются для связи между страницами в папке:

                                • Переименование папки не нарушает относительные ссылки.
                                • Ссылки не нарушаются, так как не содержат имя папки.

                                Чтобы выполнить перенаправление на страницу в другой области, укажите эту область:

                                RedirectToPage("/Index", new < area = "Services" >); 

                                Атрибут ViewData

                                Данные могут передаваться на страницу с помощью атрибута ViewDataAttribute. Значения свойств с атрибутом [ViewData] хранятся в ViewDataDictionary и загружаются из него.

                                В следующем примере AboutModel применяет атрибут [ViewData] к свойству Title :

                                public class AboutModel : PageModel < [ViewData] public string Title < get; >= "About"; public void OnGet() < >> 

                                На странице About доступ к свойству Title осуществляется как доступ к свойству модели.

                                @Model.Title

                                В макете заголовок считывается из словаря ViewData.

                                   @ViewData["Title"] - WebApplication . 

                                TempData

                                ASP.NET Core предоставляет TempData. Это свойство хранит данные до тех пор, пока они не будут прочитаны. Для проверки данных без удаления можно использовать методы Keep и Peek. TempData удобно использовать для перенаправления, когда данные требуются больше, чем для одного запроса.

                                В следующем коде значение Message задается с помощью TempData :

                                public class CreateDotModel : PageModel < private readonly AppDbContext _db; public CreateDotModel(AppDbContext db) < _db = db; >[TempData] public string Message < get; set; >[BindProperty] public Customer Customer < get; set; >public async Task OnPostAsync() < if (!ModelState.IsValid) < return Page(); >_db.Customers.Add(Customer); await _db.SaveChangesAsync(); Message = $"Customer added"; return RedirectToPage("./Index"); > > 

                                Представленная ниже разметка в файле Pages/Customers/Index.cshtml отображает значение Message с помощью TempData .

                                Msg: @Model.Message

                                Модель страницы Pages/Customers/Index.cshtml.cs применяет атрибут [TempData] ко свойству Message .

                                [TempData] public string Message

                                Дополнительные сведения см. в разделе TempData.

                                Несколько обработчиков на страницу

                                Следующая страница формирует разметку для двух обработчиков с помощью вспомогательной функции тегов asp-page-handler :

                                @page @model CreateFATHModel   

                                Enter your name.

                                Name:
                                --> -->

                                Форма в предыдущем примере включает две кнопки отправки, каждая из которых отправляет данные на отдельный URL-адрес с помощью FormActionTagHelper . Атрибут asp-page-handler является дополнением к asp-page . Атрибут asp-page-handler формирует URL-адреса, ,которые используются для отправки данных в каждый из методов обработчиков, определенных страницей. asp-page не задается, так как пример сопоставлен с текущей страницей.

                                using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; using RazorPagesContacts.Data; namespace RazorPagesContacts.Pages.Customers < public class CreateFATHModel : PageModel < private readonly AppDbContext _db; public CreateFATHModel(AppDbContext db) < _db = db; >[BindProperty] public Customer Customer < get; set; >public async Task OnPostJoinListAsync() < if (!ModelState.IsValid) < return Page(); >_db.Customers.Add(Customer); await _db.SaveChangesAsync(); return RedirectToPage("/Index"); > public async Task OnPostJoinListUCAsync() < if (!ModelState.IsValid) < return Page(); >Customer.Name = Customer.Name?.ToUpperInvariant(); return await OnPostJoinListAsync(); > > > 

                                В представленном выше коде используются именованные методы обработчика. Именованные методы обработчика создаются путем размещения определенного текста в имени после On и перед Async (если есть). В приведенном выше примере использовались методы страницы OnPostJoinListAsync и OnPostJoinListUCAsync. Если убрать OnPost и Async, имена обработчиков будут выглядеть как JoinList и JoinListUC .

                                При использовании представленного выше кода URL-путь для отправки данных в OnPostJoinListAsync будет выглядеть как https://localhost:5001/Customers/CreateFATH?handler=JoinList . URL-путь для отправки данных в OnPostJoinListUCAsync будет иметь вид https://localhost:5001/Customers/CreateFATH?handler=JoinListUC .

                                Пользовательские маршруты

                                С помощью директивы @page можно сделать следующее.

                                • Указать пользовательский маршрут к странице. Например, можно задать маршрут к странице "Сведения" /Some/Other/Path : @page "/Some/Other/Path" .
                                • Добавить сегменты к маршруту страницы по умолчанию. Например, к такому маршруту можно добавить сегмент item: @page "item" .
                                • Добавить параметры к маршруту страницы по умолчанию. Например, для страницы с @page "" может потребоваться параметр идентификатора id .

                                Поддерживается путь относительно корня, заданный знаком тильды ( ~ ) в начале пути. Например, @page "~/Some/Other/Path" — это тоже самое, что и @page "/Some/Other/Path" .

                                Если вы не хотите, чтобы в URL-адресе отображалась строка запроса ?handler=JoinList , измените маршрут так, чтобы в качестве пути в URL-адресе указывалось имя обработчика. Для настройки маршрута добавьте после директивы @page шаблон маршрута, заключенный в двойные кавычки.

                                @page "" @model CreateRouteModel   

                                Enter your name.

                                Name:

                                При использовании представленного выше кода URL-путь для отправки данных в OnPostJoinListAsync будет выглядеть как https://localhost:5001/Customers/CreateFATH/JoinList . URL-путь для отправки данных в OnPostJoinListUCAsync будет иметь вид https://localhost:5001/Customers/CreateFATH/JoinListUC .

                                Символ ? после handler означает, что параметр маршрута является необязательным.

                                Расширенная конфигурация и параметры

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

                                Для настройки расширенных параметров используйте перегрузку AddRazorPages, которая настраивает RazorPagesOptions:

                                public void ConfigureServices(IServiceCollection services) < services.AddRazorPages(options =>< options.RootDirectory = "/MyPages"; options.Conventions.AuthorizeFolder("/MyPages/Admin"); >); > 

                                Используйте RazorPagesOptions, чтобы задавать корневой каталог для страниц и добавлять для них соглашения моделей приложений. Дополнительные сведения о соглашениях см. в разделе Соглашения об авторизации Razor Pages.

                                Сведения о предварительной компиляции представлений см. на странице Компиляция представлений Razor.

                                Указание местонахождения Razor Pages в корне каталога

                                По умолчанию Razor Pages находится в корне каталога /Pages. Добавьте WithRazorPagesAtContentRoot, чтобы указать, что Razor Pages находится в корневой папке содержимого (ContentRootPath) приложения:

                                public void ConfigureServices(IServiceCollection services) < services.AddRazorPages(options =>< options.Conventions.AuthorizeFolder("/MyPages/Admin"); >) .WithRazorPagesAtContentRoot(); > 

                                Указание местонахождения Razor Pages в пользовательском корневом каталоге

                                Добавьте WithRazorPagesRoot, чтобы указать, что Razor Pages находится в пользовательском корневом каталоге в приложении (укажите относительный путь):

                                public void ConfigureServices(IServiceCollection services) < services.AddRazorPages(options =>< options.Conventions.AuthorizeFolder("/MyPages/Admin"); >) .WithRazorPagesRoot("/path/to/razor/pages"); > 

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

                                • Дополнительные общие сведения см. на странице Учебник. Начало работы с Razor Pages в ASP.NET Core.
                                • Атрибут authorize и Razor Pages
                                • Загрузить или просмотреть пример кода.
                                • Общие сведения об ASP.NET Core
                                • Справочник по синтаксису Razor для ASP.NET Core
                                • Области в ASP.NET Core
                                • Учебник. Начало работы с Razor Pages в ASP.NET Core
                                • Соглашения об авторизации Razor Pages в ASP.NET Core
                                • Соглашения для маршрутов и приложений Razor Pages в ASP.NET Core
                                • Модульные тесты Razor Pages в ASP.NET Core
                                • Частичные представления в ASP.NET Core

                                Совместная работа с нами на GitHub

                                Источник этого содержимого можно найти на GitHub, где также можно создавать и просматривать проблемы и запросы на вытягивание. Дополнительные сведения см. в нашем руководстве для участников.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *