Соглашения для маршрутов и приложений Razor Pages в ASP.NET Core
Узнайте, как использовать соглашения поставщика модели маршрутов и приложений страниц для управления маршрутизацией, обнаружением и обработкой страниц в приложениях Razor Pages.
Чтобы указать маршрут страницы, добавить сегменты маршрута или добавить параметры в маршрут, используйте директиву @page
страницы. Дополнительные сведения см. в разделе Пользовательские маршруты.
Существуют зарезервированные слова, которые нельзя использовать в качестве сегментов маршрутов или имен параметров. Дополнительные сведения см. в статье "Маршрутизация: зарезервированные имена маршрутизации".
Просмотреть или скачать образец кода (описание загрузки)
Сценарий | Этот пример демонстрирует следующие приемы. |
---|---|
Соглашения для моделей Conventions.Add |
Добавление шаблона маршрута и заголовка к страницам приложения. |
Соглашения для действий с маршрутами страниц | Добавление шаблона маршрута к страницам в папке и к одной странице. |
Соглашения для действий модели страниц
|
Добавление заголовка к страницам в папке, добавление заголовка к одной странице и настройка фабрики фильтров для добавления заголовка к страницам приложения. |
Соглашения Razor Pages настраиваются с помощью перегрузки AddRazorPages, которая настраивает RazorPagesOptions. Следующие примеры соглашений описаны далее в этом разделе:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages(options =>
{
options.Conventions.Add( ... );
options.Conventions.AddFolderRouteModelConvention(
"/OtherPages", model => { ... });
options.Conventions.AddPageRouteModelConvention(
"/About", model => { ... });
options.Conventions.AddPageRoute(
"/Contact", "TheContactPage/{text?}");
options.Conventions.AddFolderApplicationModelConvention(
"/OtherPages", model => { ... });
options.Conventions.AddPageApplicationModelConvention(
"/About", model => { ... });
options.Conventions.ConfigureFilter(model => { ... });
options.Conventions.ConfigureFilter( ... );
});
}
Порядок маршрутов
Для маршрутов указывается свойство Order, определяющее порядок обработки (сопоставления маршрутов).
Порядок маршрутов | Поведение |
---|---|
-1 | Маршрут обрабатывается до обработки других маршрутов. |
0 | Порядок не задан (значение по умолчанию). Если свойство Order не задано (Order = null ), значение Order по умолчанию для маршрута равно 0 (нулю). |
1, 2, … n | Указывает порядок обработки маршрутов. |
Маршруты обрабатываются в соответствии с соглашением.
- Маршруты обрабатываются по порядку (–1, 0, 1, 2, …, n).
- Если маршруты имеют одинаковые значения свойства
Order
, сначала сопоставляется наиболее конкретный маршрут, а затем более общие. - Если URL-адресу запроса соответствуют маршруты с одинаковым значением свойства
Order
и одинаковым количеством параметров, они обрабатываются в том порядке, в котором были добавлены в коллекцию PageConventionCollection.
По возможности старайтесь не использовать строго определенный порядок обработки маршрутов. Как правило, при маршрутизации правильный маршрут выбирается посредством сопоставления URL-адресов. Если для правильной маршрутизации запросов необходимо задать свойства Order
маршрута, схема маршрутизации приложения, скорее всего, будет малопонятна клиентам и сложна в обслуживании. Старайтесь упростить схему маршрутизации приложения. В примере приложения требуется явно определенный порядок обработки маршрутов для демонстрации нескольких сценариев маршрутизации на основе одного приложения. Однако в рабочих приложениях следует избегать задания свойства Order
для маршрутов.
Средства маршрутизации в Razor Pages и контроллере MVC имеют общую реализацию. Сведения о порядке маршрута в разделах MVC доступны в разделе "Маршрутизация для действий контроллера: упорядочивание маршрутов атрибутов".
Соглашения для моделей
Добавьте делегат для IPageConvention, чтобы добавить соглашения для модели, применяемые к Razor Pages.
Добавление соглашения для модели маршрутов ко всем страницам
Используйте свойство Conventions, чтобы создать и добавить IPageRouteModelConvention в коллекцию экземпляров IPageConvention, которые применяются при формировании модели маршрутов страниц.
В этом примере приложения есть класс GlobalTemplatePageRouteModelConvention
для добавления шаблона маршрута {globalTemplate?}
ко всем страницам приложения:
using Microsoft.AspNetCore.Mvc.ApplicationModels;
namespace SampleApp.Conventions;
public class GlobalTemplatePageRouteModelConvention : IPageRouteModelConvention
{
public void Apply(PageRouteModel model)
{
var selectorCount = model.Selectors.Count;
for (var i = 0; i < selectorCount; i++)
{
var selector = model.Selectors[i];
model.Selectors.Add(new SelectorModel
{
AttributeRouteModel = new AttributeRouteModel
{
Order = 1,
Template = AttributeRouteModel.CombineTemplates(
selector.AttributeRouteModel!.Template,
"{globalTemplate?}"),
}
});
}
}
}
В предыдущем коде:
- PageRouteModel передается методу Apply.
- PageRouteModel.Selectors получает количество селекторов.
- Добавляется новый SelectorModel, который содержит AttributeRouteModel.
Параметры Razor Pages, такие как добавление Conventions, добавляются при добавлении Razor Pages в коллекцию служб. Пример см. в образце приложения.
using Microsoft.AspNetCore.Mvc.ApplicationModels;
using Microsoft.EntityFrameworkCore;
using SampleApp.Conventions;
using SampleApp.Data;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<AppDbContext>(options =>
options.UseInMemoryDatabase("InMemoryDb"));
builder.Services.AddRazorPages(options =>
{
options.Conventions.Add(new GlobalTemplatePageRouteModelConvention());
options.Conventions.AddFolderRouteModelConvention("/OtherPages", model =>
{
var selectorCount = model.Selectors.Count;
for (var i = 0; i < selectorCount; i++)
{
var selector = model.Selectors[i];
model.Selectors.Add(new SelectorModel
{
AttributeRouteModel = new AttributeRouteModel
{
Order = 2,
Template = AttributeRouteModel.CombineTemplates(
selector.AttributeRouteModel!.Template,
"{otherPagesTemplate?}"),
}
});
}
});
options.Conventions.AddPageRouteModelConvention("/About", model =>
{
var selectorCount = model.Selectors.Count;
for (var i = 0; i < selectorCount; i++)
{
var selector = model.Selectors[i];
model.Selectors.Add(new SelectorModel
{
AttributeRouteModel = new AttributeRouteModel
{
Order = 2,
Template = AttributeRouteModel.CombineTemplates(
selector.AttributeRouteModel!.Template,
"{aboutTemplate?}"),
}
});
}
});
});
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseAuthorization();
app.MapRazorPages();
app.Run();
Давайте рассмотрим класс GlobalTemplatePageRouteModelConvention
:
using Microsoft.AspNetCore.Mvc.ApplicationModels;
namespace SampleApp.Conventions;
public class GlobalTemplatePageRouteModelConvention : IPageRouteModelConvention
{
public void Apply(PageRouteModel model)
{
var selectorCount = model.Selectors.Count;
for (var i = 0; i < selectorCount; i++)
{
var selector = model.Selectors[i];
model.Selectors.Add(new SelectorModel
{
AttributeRouteModel = new AttributeRouteModel
{
Order = 1,
Template = AttributeRouteModel.CombineTemplates(
selector.AttributeRouteModel!.Template,
"{globalTemplate?}"),
}
});
}
}
}
Свойству Order для AttributeRouteModel задано значение 1
. Это обеспечивает описанное ниже поведение сопоставления маршрутов в примере приложения.
Шаблон маршрута для
TheContactPage/{text?}
добавляется далее в этом разделе. МаршрутContact Page
по умолчанию имеет порядокnull
(Order = 0
), поэтому он сопоставляется до шаблона маршрута{globalTemplate?}
с порядкомOrder = 1
.Шаблон маршрута
{aboutTemplate?}
показан в приведенном выше коде. Шаблону{aboutTemplate?}
задано свойствоOrder
, равное2
. При запросе страницы About по адресу/About/RouteDataValue
значение RouteDataValue загружается вRouteData.Values["globalTemplate"]
(Order = 1
), а не вRouteData.Values["aboutTemplate"]
(Order = 2
). Это происходит из-за значения свойстваOrder
.Шаблон маршрута
{otherPagesTemplate?}
показан в приведенном выше коде. Шаблону{otherPagesTemplate?}
задано свойствоOrder
, равное2
. При запросе любой страницы в парке Pages/OtherPages с параметром маршрута:Например
/OtherPages/Page1/xyz
.Значение
"xyz"
из данных маршрута загружается вRouteData.Values["globalTemplate"]
(Order = 1
).RouteData.Values["otherPagesTemplate"]
с порядком (Order = 2
) не загружается из-за того, что свойство2
вOrder
имеет более высокое значение.
По возможности не устанавливайте параметр Order
. Если для Order
не задано значение, по умолчанию используется Order = 0
. Для выбора правильного маршрута следует использовать маршрутизацию, а не свойство Order
.
Запросите страницу About
из примера по адресу localhost:{port}/About/GlobalRouteValue
и проверьте результат:
Этот пример приложения использует пакет NuGet Rick.Docs.Samples.RouteInfo для отображения сведений о маршрутизации в выходных данных для ведения журнала. При использовании localhost:{port}/About/GlobalRouteValue
средство ведения журнала отображает запрос, Order
, и используемый шаблон:
info: SampleApp.Pages.AboutModel[0]
/About/GlobalRouteValue Order = 1 Template = About/{globalTemplate?}
Добавление соглашения для модели приложений ко всем страницам
Используйте свойство Conventions, чтобы создать и добавить IPageApplicationModelConvention в коллекцию экземпляров IPageConvention, которые применяются при формировании модели приложения страницы.
Для демонстрации этих и других соглашений далее в этом разделе в пример приложения включен класс AddHeaderAttribute
. Конструктор класса принимает строку name
и массив строк values
. Эти значения используются в его методе OnResultExecuting
для задания заголовка ответа. Класс показан полностью в разделе Соглашения для действий модели страниц далее.
Пример приложения использует класс AddHeaderAttribute
, чтобы добавить заголовок GlobalHeader
ко всем страницам в приложении:
public class GlobalHeaderPageApplicationModelConvention
: IPageApplicationModelConvention
{
public void Apply(PageApplicationModel model)
{
model.Filters.Add(new AddHeaderAttribute(
"GlobalHeader", new string[] { "Global Header Value" }));
}
}
Program.cs
:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<AppDbContext>(options =>
options.UseInMemoryDatabase("InMemoryDb"));
builder.Services.AddRazorPages(options =>
{
options.Conventions.Add(new GlobalTemplatePageRouteModelConvention());
options.Conventions.Add(new GlobalHeaderPageApplicationModelConvention());
Запросите страницу About по адресу localhost:{port}/About
из примера и посмотрите заголовки, чтобы проверить результат:
Добавление соглашения для модели обработчика ко всем страницам
Используйте свойство Conventions, чтобы создать и добавить IPageHandlerModelConvention в коллекцию экземпляров IPageConvention, которые применяются при формировании модели обработчика страниц.
public class GlobalPageHandlerModelConvention
: IPageHandlerModelConvention
{
public void Apply(PageHandlerModel model)
{
// Access the PageHandlerModel
}
}
Соглашения для действий с маршрутами страниц
Поставщик модели маршрутов по умолчанию, который является производным от IPageRouteModelProvider, использует соглашения, создающие точки расширения для настройки маршрутов страниц.
Соглашение для модели маршрутов папки
Используйте метод AddFolderRouteModelConvention, чтобы создать и добавить интерфейс IPageRouteModelConvention, вызывающий действие в классе PageRouteModel для всех страниц в указанной папке.
Пример приложения использует AddFolderRouteModelConvention для добавления шаблона маршрута {otherPagesTemplate?}
к страницам в папке OtherPages:
options.Conventions.AddFolderRouteModelConvention("/OtherPages", model =>
{
var selectorCount = model.Selectors.Count;
for (var i = 0; i < selectorCount; i++)
{
var selector = model.Selectors[i];
model.Selectors.Add(new SelectorModel
{
AttributeRouteModel = new AttributeRouteModel
{
Order = 2,
Template = AttributeRouteModel.CombineTemplates(
selector.AttributeRouteModel!.Template,
"{otherPagesTemplate?}"),
}
});
}
});
Свойству Order для AttributeRouteModel задано значение 2
. Это гарантирует, что при указании одного значения маршрута приоритетно выбирается значение данных маршрута из шаблона {globalTemplate?}
, которому ранее в разделе было присвоено значение 1
. При запросе страницы в папке Pages/OtherPages со значением параметра маршрута (например, /OtherPages/Page1/RouteDataValue
), RouteDataValue загружается в RouteData.Values["globalTemplate"]
(Order = 1
), а не в RouteData.Values["otherPagesTemplate"]
(Order = 2
). Это происходит из-за значения свойства Order
.
По возможности не задавайте свойство Order
, чтобы оно имело значение Order = 0
. Предоставьте системе маршрутизации возможность выбирать правильный маршрут.
Запросите страницу Page1 по адресу localhost:5000/OtherPages/Page1/GlobalRouteValue/OtherPagesRouteValue
из примера и проверьте результат:
Соглашение для модели маршрутов страницы
Используйте метод AddPageRouteModelConvention, чтобы создать и добавить интерфейс IPageRouteModelConvention, вызывающий действие в классе PageRouteModel для страницы с указанным именем.
Пример приложения использует AddPageRouteModelConvention
для добавления шаблона маршрута {aboutTemplate?}
к странице About:
options.Conventions.AddPageRouteModelConvention("/About", model =>
{
var selectorCount = model.Selectors.Count;
for (var i = 0; i < selectorCount; i++)
{
var selector = model.Selectors[i];
model.Selectors.Add(new SelectorModel
{
AttributeRouteModel = new AttributeRouteModel
{
Order = 2,
Template = AttributeRouteModel.CombineTemplates(
selector.AttributeRouteModel!.Template,
"{aboutTemplate?}"),
}
});
}
});
Свойству Order для AttributeRouteModel задано значение 2
. Это гарантирует, что при указании одного значения маршрута приоритетно выбирается значение данных маршрута из шаблона {globalTemplate?}
, которому ранее в разделе было присвоено значение 1
. При запросе страницы About со значением параметра маршрута по адресу /About/RouteDataValue
, RouteDataValue загружается в RouteData.Values["globalTemplate"]
(Order = 1
), а не в RouteData.Values["aboutTemplate"]
(Order = 2
). Это происходит из-за значения свойства Order
.
По возможности не задавайте свойство Order
, чтобы оно имело значение Order = 0
. Предоставьте системе маршрутизации возможность выбирать правильный маршрут.
Запросите страницу About по адресу localhost:{port}/About/GlobalRouteValue/AboutRouteValue
из примера и проверьте результат:
Средство ведения журнала отображает следующее:
info: SampleApp.Pages.AboutModel[0]
/About/GlobalRouteValue/AboutRouteValue Order = 2 Template = About/{globalTemplate?}/{aboutTemplate?}
Использование преобразователя параметров для настройки маршрутов страницы
Подробнее см. Преобразователи параметров.
Настройка маршрута страницы
Используйте метод AddPageRoute, чтобы настроить маршрут к странице по указанному пути страницы. Созданные ссылки на страницу будут использовать заданный маршрут. Для установления маршрута метод AddPageRoute использует AddPageRouteModelConvention.
Этот пример приложения создает маршрут к /TheContactPage
для страницы Contact
Razor:
options.Conventions.AddPageRoute("/Contact", "TheContactPage/{text?}");
На страницу Contact
также можно перейти по адресу /
Contact1` через маршрут по умолчанию.
Настраиваемый маршрут на страницу Contact
в этом примере приложения позволяет использовать необязательный сегмент маршрута text
({text?}
). Страница также включает этот необязательный сегмент в своей директиве @page
на случай, если посетитель переходит на страницу по маршруту /Contact
:
@page "{text?}"
@model ContactModel
@{
ViewData["Title"] = "Contact";
}
<h1>@ViewData["Title"]</h1>
<h2>@Model.Message</h2>
<address>
One Microsoft Way<br>
Redmond, WA 98052-6399<br>
<abbr title="Phone">P:</abbr>
425.555.0100
</address>
<address>
<strong>Support:</strong> <a href="mailto:Support@example.com">Support@example.com</a><br>
<strong>Marketing:</strong> <a href="mailto:Marketing@example.com">Marketing@example.com</a>
</address>
<p>@Model.RouteDataTextTemplateValue</p>
Обратите внимание, что URL-адрес, созданный для ссылки Contact на отображенной странице, отражает обновленный маршрут:
Перейдите на страницу Contact
по ее обычному маршруту /Contact
или по настроенному маршруту /TheContactPage
. Если вы укажете дополнительный сегмент маршрута text
, страница отобразит этот сегмент в HTML-кодировке:
Соглашения для действий модели страниц
Поставщик модели страниц по умолчанию, который реализует IPageApplicationModelProvider, использует соглашения, создающие точки расширения для настройки моделей страниц. Эти соглашения полезны при создании и изменении для обнаружения и обработки страниц.
В примерах этого раздела образец приложения использует класс AddHeaderAttribute
, который является ResultFilterAttribute и применяет заголовок ответа:
public class AddHeaderAttribute : ResultFilterAttribute
{
private readonly string _name;
private readonly string[] _values;
public AddHeaderAttribute(string name, string[] values)
{
_name = name;
_values = values;
}
public override void OnResultExecuting(ResultExecutingContext context)
{
context.HttpContext.Response.Headers.Add(_name, _values);
base.OnResultExecuting(context);
}
}
Образец показывает использование соглашений для применения атрибута ко всем страницам в папке и к одной странице.
Соглашение для модели приложений папки
Используйте метод AddFolderApplicationModelConvention, чтобы создать и добавить интерфейс IPageApplicationModelConvention, вызывающий действие в экземплярах PageApplicationModel для всех страниц в указанной папке.
Пример демонстрирует использование AddFolderApplicationModelConvention
путем добавления заголовка OtherPagesHeader
к страницам в папке OtherPages приложения:
options.Conventions.AddFolderApplicationModelConvention("/OtherPages", model =>
{
model.Filters.Add(new AddHeaderAttribute(
"OtherPagesHeader", new string[] { "OtherPages Header Value" }));
});
Запросите страницу Page1 по адресу localhost:5000/OtherPages/Page1
из примера и посмотрите заголовки, чтобы проверить результат:
Соглашение для модели приложений страницы
Используйте метод AddPageApplicationModelConvention, чтобы создать и добавить интерфейс IPageApplicationModelConvention, вызывающий действие в классе PageApplicationModel для страницы с указанным именем.
Пример демонстрирует использование AddPageApplicationModelConvention
путем добавления заголовка AboutHeader
на страницу About:
options.Conventions.AddPageApplicationModelConvention("/About", model =>
{
model.Filters.Add(new AddHeaderAttribute(
"AboutHeader", new string[] { "About Header Value" }));
});
Запросите страницу About по адресу localhost:5000/About
из примера и посмотрите заголовки, чтобы проверить результат:
Настройка фильтра
Для настройки применяемого фильтра используется метод ConfigureFilter. Вы можете создать класс фильтра, но пример приложения показывает реализацию фильтра в лямбда-выражении, которое реализовано "за кулисами" в качестве фабрики, возвращающей фильтр:
options.Conventions.ConfigureFilter(model =>
{
if (model.RelativePath.Contains("OtherPages/Page2"))
{
return new AddHeaderAttribute(
"OtherPagesPage2Header",
new string[] { "OtherPages/Page2 Header Value" });
}
return new EmptyFilter();
});
Модель приложений страницы используется для проверки относительного пути на наличие сегментов, ведущих к странице Page2 в папке OtherPages. Если условие выполняется, добавляется заголовок. Если нет, применяется EmptyFilter
.
EmptyFilter
является фильтром действий. Так как в Razor Pages фильтры действий не учитываются, EmptyFilter
не оказывает действия, как и задумано, если путь не содержит OtherPages/Page2
.
Запросите страницу Page2 по адресу localhost:5000/OtherPages/Page2
из примера и посмотрите заголовки, чтобы проверить результат:
Настройка фабрики фильтров
Метод ConfigureFilter позволяет настроить указанное производство так, чтобы фильтры применялись ко всем страницам Razor Pages.
В примере приложения приведен образец использования фабрики фильтров путем добавления на страницы приложения заголовка FilterFactoryHeader
с двумя значениями:
options.Conventions.ConfigureFilter(new AddHeaderWithFactory());
AddHeaderWithFactory.cs
:
public class AddHeaderWithFactory : IFilterFactory
{
// Implement IFilterFactory
public IFilterMetadata CreateInstance(IServiceProvider serviceProvider)
{
return new AddHeaderFilter();
}
private class AddHeaderFilter : IResultFilter
{
public void OnResultExecuting(ResultExecutingContext context)
{
context.HttpContext.Response.Headers.Add(
"FilterFactoryHeader",
new string[]
{
"Filter Factory Header Value 1",
"Filter Factory Header Value 2"
});
}
public void OnResultExecuted(ResultExecutedContext context)
{
}
}
public bool IsReusable
{
get
{
return false;
}
}
}
Запросите страницу About по адресу localhost:5000/About
из примера и посмотрите заголовки, чтобы проверить результат:
Фильтры MVC и фильтр страниц (IPageFilter)
Фильтры действий MVC игнорируются в Razor Pages, так как Razor Pages использует методы обработчиков. Доступны для использования другие типы фильтров MVC: фильтры авторизации, исключений, ресурсов и результатов. Дополнительные сведения см. в разделе Фильтры.
Фильтр страниц (IPageFilter) — это фильтр, применяемый к страницам Razor Pages. Дополнительные сведения см. в разделе Методы фильтрации для Razor Pages.
Дополнительные ресурсы
Узнайте, как использовать соглашения поставщика модели маршрутов и приложений страниц для управления маршрутизацией, обнаружением и обработкой страниц в приложениях Razor Pages.
Когда вам необходимо настроить уникальные маршруты для отдельных страниц, используйте соглашение AddPageRoute, описанное далее в этом разделе.
Чтобы указать маршрут страницы, добавить сегменты маршрута или добавить параметры в маршрут, используйте директиву @page
страницы. Дополнительные сведения см. в разделе Пользовательские маршруты.
Существуют зарезервированные слова, которые нельзя использовать в качестве сегментов маршрутов или имен параметров. Дополнительные сведения см. в статье "Маршрутизация: зарезервированные имена маршрутизации".
Просмотреть или скачать образец кода (описание загрузки)
Сценарий | Что демонстрирует пример |
---|---|
Соглашения для моделей Conventions.Add
|
Добавление шаблона маршрута и заголовка к страницам приложения. |
Соглашения для действий с маршрутами страниц
|
Добавление шаблона маршрута к страницам в папке и к одной странице. |
Соглашения для действий модели страниц
|
Добавление заголовка к страницам в папке, добавление заголовка к одной странице и настройка фабрики фильтров для добавления заголовка к страницам приложения. |
Соглашения Razor Pages настраиваются с помощью перегрузки AddRazorPages, которая настраивает RazorPagesOptions в Startup.ConfigureServices
. Следующие примеры соглашений описаны далее в этом разделе:
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages(options =>
{
options.Conventions.Add( ... );
options.Conventions.AddFolderRouteModelConvention(
"/OtherPages", model => { ... });
options.Conventions.AddPageRouteModelConvention(
"/About", model => { ... });
options.Conventions.AddPageRoute(
"/Contact", "TheContactPage/{text?}");
options.Conventions.AddFolderApplicationModelConvention(
"/OtherPages", model => { ... });
options.Conventions.AddPageApplicationModelConvention(
"/About", model => { ... });
options.Conventions.ConfigureFilter(model => { ... });
options.Conventions.ConfigureFilter( ... );
});
}
Порядок маршрутов
Для маршрутов указывается свойство Order, определяющее порядок обработки (сопоставления маршрутов).
Порядок | Поведение |
---|---|
-1 | Маршрут обрабатывается до обработки других маршрутов. |
0 | Порядок не задан (значение по умолчанию). Если свойство Order не задано (Order = null ), значение Order по умолчанию для маршрута равно 0 (нулю). |
1, 2, … n | Указывает порядок обработки маршрутов. |
Маршруты обрабатываются в соответствии с соглашением.
- Маршруты обрабатываются по порядку (–1, 0, 1, 2, …, n).
- Если маршруты имеют одинаковые значения свойства
Order
, сначала сопоставляется наиболее конкретный маршрут, а затем более общие. - Если URL-адресу запроса соответствуют маршруты с одинаковым значением свойства
Order
и одинаковым количеством параметров, они обрабатываются в том порядке, в котором были добавлены в коллекцию PageConventionCollection.
По возможности старайтесь не использовать строго определенный порядок обработки маршрутов. Как правило, при маршрутизации правильный маршрут выбирается посредством сопоставления URL-адресов. Если для правильной маршрутизации запросов необходимо задать свойства Order
маршрута, схема маршрутизации приложения, скорее всего, будет малопонятна клиентам и сложна в обслуживании. Старайтесь упростить схему маршрутизации приложения. В примере приложения требуется явно определенный порядок обработки маршрутов для демонстрации нескольких сценариев маршрутизации на основе одного приложения. Однако в рабочих приложениях следует избегать задания свойства Order
для маршрутов.
Средства маршрутизации в Razor Pages и контроллере MVC имеют общую реализацию. Сведения о порядке маршрута в разделах MVC доступны в разделе "Маршрутизация для действий контроллера: упорядочивание маршрутов атрибутов".
Соглашения для моделей
Добавьте делегат для IPageConvention, чтобы добавить соглашения для модели, применяемые к Razor Pages.
Добавление соглашения для модели маршрутов ко всем страницам
Используйте свойство Conventions, чтобы создать и добавить IPageRouteModelConvention в коллекцию экземпляров IPageConvention, которые применяются при формировании модели маршрутов страниц.
В примере приложения шаблон маршрута {globalTemplate?}
добавляется ко всем страницам приложения:
public class GlobalTemplatePageRouteModelConvention
: IPageRouteModelConvention
{
public void Apply(PageRouteModel model)
{
var selectorCount = model.Selectors.Count;
for (var i = 0; i < selectorCount; i++)
{
var selector = model.Selectors[i];
model.Selectors.Add(new SelectorModel
{
AttributeRouteModel = new AttributeRouteModel
{
Order = 1,
Template = AttributeRouteModel.CombineTemplates(
selector.AttributeRouteModel.Template,
"{globalTemplate?}"),
}
});
}
}
}
Свойству Order для AttributeRouteModel задано значение 1
. Это обеспечивает описанное ниже поведение сопоставления маршрутов в примере приложения.
- Шаблон маршрута для
TheContactPage/{text?}
добавляется далее в разделе. Маршрут страницы Contact по умолчанию имеет порядокnull
(Order = 0
), поэтому он сопоставляется до шаблона маршрута{globalTemplate?}
. - Шаблон маршрута
{aboutTemplate?}
добавляется далее в разделе. Шаблону{aboutTemplate?}
задано свойствоOrder
, равное2
. При запросе страницы About по адресу/About/RouteDataValue
значение RouteDataValue загружается вRouteData.Values["globalTemplate"]
(Order = 1
), а не вRouteData.Values["aboutTemplate"]
(Order = 2
). Это происходит из-за значения свойстваOrder
. - Шаблон маршрута
{otherPagesTemplate?}
добавляется далее в разделе. Шаблону{otherPagesTemplate?}
задано свойствоOrder
, равное2
. При запросе любой страницы в папке Pages/OtherPages с параметром маршрута (например,/OtherPages/Page1/RouteDataValue
), RouteDataValue загружается вRouteData.Values["globalTemplate"]
(Order = 1
), а не вRouteData.Values["otherPagesTemplate"]
(Order = 2
). Это происходит из-за значения свойстваOrder
.
По возможности не задавайте свойство Order
, чтобы оно имело значение Order = 0
. Предоставьте системе маршрутизации возможность выбирать правильный маршрут.
Параметры Razor Pages, такие как добавление Conventions, добавляются при добавлении Razor Pages в коллекцию служб в Startup.ConfigureServices
. Пример см. в образце приложения.
options.Conventions.Add(new GlobalTemplatePageRouteModelConvention());
Запросите страницу About по адресу localhost:5000/About/GlobalRouteValue
из примера и проверьте результат:
Добавление соглашения для модели приложений ко всем страницам
Используйте свойство Conventions, чтобы создать и добавить IPageApplicationModelConvention в коллекцию экземпляров IPageConvention, которые применяются при формировании модели приложения страницы.
Для демонстрации этих и других соглашений далее в этом разделе в пример приложения включен класс AddHeaderAttribute
. Конструктор класса принимает строку name
и массив строк values
. Эти значения используются в его методе OnResultExecuting
для задания заголовка ответа. Класс показан полностью в разделе Соглашения для действий модели страниц далее.
Пример приложения использует класс AddHeaderAttribute
, чтобы добавить заголовок GlobalHeader
ко всем страницам в приложении:
public class GlobalHeaderPageApplicationModelConvention
: IPageApplicationModelConvention
{
public void Apply(PageApplicationModel model)
{
model.Filters.Add(new AddHeaderAttribute(
"GlobalHeader", new string[] { "Global Header Value" }));
}
}
Startup.cs
:
options.Conventions.Add(new GlobalHeaderPageApplicationModelConvention());
Запросите страницу About по адресу localhost:5000/About
из примера и посмотрите заголовки, чтобы проверить результат:
Добавление соглашения для модели обработчика ко всем страницам
Используйте свойство Conventions, чтобы создать и добавить IPageHandlerModelConvention в коллекцию экземпляров IPageConvention, которые применяются при формировании модели обработчика страниц.
public class GlobalPageHandlerModelConvention
: IPageHandlerModelConvention
{
public void Apply(PageHandlerModel model)
{
// Access the PageHandlerModel
}
}
Startup.cs
:
options.Conventions.Add(new GlobalPageHandlerModelConvention());
Соглашения для действий с маршрутами страниц
Поставщик модели маршрутов по умолчанию, который является производным от IPageRouteModelProvider, использует соглашения, создающие точки расширения для настройки маршрутов страниц.
Соглашение для модели маршрутов папки
Используйте метод AddFolderRouteModelConvention, чтобы создать и добавить интерфейс IPageRouteModelConvention, вызывающий действие в классе PageRouteModel для всех страниц в указанной папке.
Пример приложения использует AddFolderRouteModelConvention для добавления шаблона маршрута {otherPagesTemplate?}
к страницам в папке OtherPages:
options.Conventions.AddFolderRouteModelConvention("/OtherPages", model =>
{
var selectorCount = model.Selectors.Count;
for (var i = 0; i < selectorCount; i++)
{
var selector = model.Selectors[i];
model.Selectors.Add(new SelectorModel
{
AttributeRouteModel = new AttributeRouteModel
{
Order = 2,
Template = AttributeRouteModel.CombineTemplates(
selector.AttributeRouteModel.Template,
"{otherPagesTemplate?}"),
}
});
}
});
Свойству Order для AttributeRouteModel задано значение 2
. Это гарантирует, что при указании одного значения маршрута приоритетно выбирается значение данных маршрута из шаблона {globalTemplate?}
, которому ранее в разделе было присвоено значение 1
. При запросе страницы в папке Pages/OtherPages со значением параметра маршрута (например, /OtherPages/Page1/RouteDataValue
), RouteDataValue загружается в RouteData.Values["globalTemplate"]
(Order = 1
), а не в RouteData.Values["otherPagesTemplate"]
(Order = 2
). Это происходит из-за значения свойства Order
.
По возможности не задавайте свойство Order
, чтобы оно имело значение Order = 0
. Предоставьте системе маршрутизации возможность выбирать правильный маршрут.
Запросите страницу Page1 по адресу localhost:5000/OtherPages/Page1/GlobalRouteValue/OtherPagesRouteValue
из примера и проверьте результат:
Соглашение для модели маршрутов страницы
Используйте метод AddPageRouteModelConvention, чтобы создать и добавить интерфейс IPageRouteModelConvention, вызывающий действие в классе PageRouteModel для страницы с указанным именем.
Пример приложения использует AddPageRouteModelConvention
для добавления шаблона маршрута {aboutTemplate?}
к странице About:
options.Conventions.AddPageRouteModelConvention("/About", model =>
{
var selectorCount = model.Selectors.Count;
for (var i = 0; i < selectorCount; i++)
{
var selector = model.Selectors[i];
model.Selectors.Add(new SelectorModel
{
AttributeRouteModel = new AttributeRouteModel
{
Order = 2,
Template = AttributeRouteModel.CombineTemplates(
selector.AttributeRouteModel.Template,
"{aboutTemplate?}"),
}
});
}
});
Свойству Order для AttributeRouteModel задано значение 2
. Это гарантирует, что при указании одного значения маршрута приоритетно выбирается значение данных маршрута из шаблона {globalTemplate?}
, которому ранее в разделе было присвоено значение 1
. При запросе страницы About со значением параметра маршрута по адресу /About/RouteDataValue
, RouteDataValue загружается в RouteData.Values["globalTemplate"]
(Order = 1
), а не в RouteData.Values["aboutTemplate"]
(Order = 2
). Это происходит из-за значения свойства Order
.
По возможности не задавайте свойство Order
, чтобы оно имело значение Order = 0
. Предоставьте системе маршрутизации возможность выбирать правильный маршрут.
Запросите страницу About по адресу localhost:5000/About/GlobalRouteValue/AboutRouteValue
из примера и проверьте результат:
Использование преобразователя параметров для настройки маршрутов страницы
Маршруты страниц, создаваемые платформой ASP.NET Core, можно настроить, используя преобразователь параметров. Преобразователь параметров реализует IOutboundParameterTransformer
и преобразует значения параметров. Например, пользовательский преобразователь параметра SlugifyParameterTransformer
изменяет значение маршрута SubscriptionManagement
на subscription-management
.
Соглашение для модели маршрутов страницы PageRouteTransformerConvention
применяет преобразователь параметров к сегментам имен папок и файлов автоматически создаваемых маршрутов страниц в приложении. Например, для файла Razor Pages по пути /Pages/SubscriptionManagement/ViewAll.cshtml
маршрут меняется с /SubscriptionManagement/ViewAll
на /subscription-management/view-all
.
PageRouteTransformerConvention
преобразует только те сегменты маршрута страницы, которые создаются автоматически на основе имен папок и файлов в Razor Pages. Он не преобразует сегменты маршрута, добавленные с помощью директивы @page
. Это соглашение также не преобразует маршруты, добавленные с помощью AddPageRoute.
PageRouteTransformerConvention
регистрируется в качестве параметра в Startup.ConfigureServices
.
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages(options =>
{
options.Conventions.Add(
new PageRouteTransformerConvention(
new SlugifyParameterTransformer()));
});
}
public class SlugifyParameterTransformer : IOutboundParameterTransformer
{
public string TransformOutbound(object value)
{
if (value == null) { return null; }
return Regex.Replace(value.ToString(),
"([a-z])([A-Z])",
"$1-$2",
RegexOptions.CultureInvariant,
TimeSpan.FromMilliseconds(100)).ToLowerInvariant();
}
}
Предупреждение
При использовании System.Text.RegularExpressions для обработки ненадежных входных данных передайте время ожидания. Злонамеренный пользователь может предоставить входные данные для RegularExpressions
, что делает возможными атаки типа "отказ в обслуживании". API платформы ASP.NET Core, использующие RegularExpressions
, передают время ожидания.
Настройка маршрута страницы
Используйте метод AddPageRoute, чтобы настроить маршрут к странице по указанному пути страницы. Созданные ссылки на страницу будут использовать заданный вами маршрут. Для установления маршрута метод AddPageRoute
использует AddPageRouteModelConvention
.
Пример приложения создает маршрут к /TheContactPage
для файла Contact.cshtml
:
options.Conventions.AddPageRoute("/Contact", "TheContactPage/{text?}");
На страницу Contact также можно перейти с помощью /Contact
через маршрут по умолчанию.
Настраиваемый маршрут на страницу Contact в примере приложения позволяет использовать необязательный сегмент маршрута text
({text?}
). Страница также включает этот необязательный сегмент в своей директиве @page
на случай, если посетитель переходит на страницу по маршруту /Contact
:
@page "{text?}"
@model ContactModel
@{
ViewData["Title"] = "Contact";
}
<h1>@ViewData["Title"]</h1>
<h2>@Model.Message</h2>
<address>
One Microsoft Way<br>
Redmond, WA 98052-6399<br>
<abbr title="Phone">P:</abbr>
425.555.0100
</address>
<address>
<strong>Support:</strong> <a href="mailto:Support@example.com">Support@example.com</a><br>
<strong>Marketing:</strong> <a href="mailto:Marketing@example.com">Marketing@example.com</a>
</address>
<p>@Model.RouteDataTextTemplateValue</p>
Обратите внимание, что URL-адрес, созданный для ссылки Contact на отображенной странице, отражает обновленный маршрут:
Перейдите на страницу Contact по ее обычному маршруту /Contact
или по настроенному маршруту /TheContactPage
. Если вы укажете дополнительный сегмент маршрута text
, страница отобразит этот сегмент в HTML-кодировке:
Соглашения для действий модели страниц
Поставщик модели страниц по умолчанию, который реализует IPageApplicationModelProvider, использует соглашения, создающие точки расширения для настройки моделей страниц. Эти соглашения полезны при создании и изменении для обнаружения и обработки страниц.
В примерах этого раздела образец приложения использует класс AddHeaderAttribute
, который является ResultFilterAttribute и применяет заголовок ответа:
public class AddHeaderAttribute : ResultFilterAttribute
{
private readonly string _name;
private readonly string[] _values;
public AddHeaderAttribute(string name, string[] values)
{
_name = name;
_values = values;
}
public override void OnResultExecuting(ResultExecutingContext context)
{
context.HttpContext.Response.Headers.Add(_name, _values);
base.OnResultExecuting(context);
}
}
Образец показывает использование соглашений для применения атрибута ко всем страницам в папке и к одной странице.
Соглашение для модели приложений папки
Используйте метод AddFolderApplicationModelConvention, чтобы создать и добавить интерфейс IPageApplicationModelConvention, вызывающий действие в экземплярах PageApplicationModel для всех страниц в указанной папке.
Пример демонстрирует использование AddFolderApplicationModelConvention
путем добавления заголовка OtherPagesHeader
к страницам в папке OtherPages приложения:
options.Conventions.AddFolderApplicationModelConvention("/OtherPages", model =>
{
model.Filters.Add(new AddHeaderAttribute(
"OtherPagesHeader", new string[] { "OtherPages Header Value" }));
});
Запросите страницу Page1 по адресу localhost:5000/OtherPages/Page1
из примера и посмотрите заголовки, чтобы проверить результат:
Соглашение для модели приложений страницы
Используйте метод AddPageApplicationModelConvention, чтобы создать и добавить интерфейс IPageApplicationModelConvention, вызывающий действие в классе PageApplicationModel для страницы с указанным именем.
Пример демонстрирует использование AddPageApplicationModelConvention
путем добавления заголовка AboutHeader
на страницу About:
options.Conventions.AddPageApplicationModelConvention("/About", model =>
{
model.Filters.Add(new AddHeaderAttribute(
"AboutHeader", new string[] { "About Header Value" }));
});
Запросите страницу About по адресу localhost:5000/About
из примера и посмотрите заголовки, чтобы проверить результат:
Настройка фильтра
Для настройки применяемого фильтра используется метод ConfigureFilter. Вы можете создать класс фильтра, но пример приложения показывает реализацию фильтра в лямбда-выражении, которое реализовано "за кулисами" в качестве фабрики, возвращающей фильтр:
options.Conventions.ConfigureFilter(model =>
{
if (model.RelativePath.Contains("OtherPages/Page2"))
{
return new AddHeaderAttribute(
"OtherPagesPage2Header",
new string[] { "OtherPages/Page2 Header Value" });
}
return new EmptyFilter();
});
Модель приложений страницы используется для проверки относительного пути на наличие сегментов, ведущих к странице Page2 в папке OtherPages. Если условие выполняется, добавляется заголовок. Если нет, применяется EmptyFilter
.
EmptyFilter
является фильтром действий. Так как в Razor Pages фильтры действий не учитываются, EmptyFilter
не оказывает действия, как и задумано, если путь не содержит OtherPages/Page2
.
Запросите страницу Page2 по адресу localhost:5000/OtherPages/Page2
из примера и посмотрите заголовки, чтобы проверить результат:
Настройка фабрики фильтров
Метод ConfigureFilter позволяет настроить указанное производство так, чтобы фильтры применялись ко всем страницам Razor Pages.
В примере приложения приведен образец использования фабрики фильтров путем добавления на страницы приложения заголовка FilterFactoryHeader
с двумя значениями:
options.Conventions.ConfigureFilter(new AddHeaderWithFactory());
AddHeaderWithFactory.cs
:
public class AddHeaderWithFactory : IFilterFactory
{
// Implement IFilterFactory
public IFilterMetadata CreateInstance(IServiceProvider serviceProvider)
{
return new AddHeaderFilter();
}
private class AddHeaderFilter : IResultFilter
{
public void OnResultExecuting(ResultExecutingContext context)
{
context.HttpContext.Response.Headers.Add(
"FilterFactoryHeader",
new string[]
{
"Filter Factory Header Value 1",
"Filter Factory Header Value 2"
});
}
public void OnResultExecuted(ResultExecutedContext context)
{
}
}
public bool IsReusable
{
get
{
return false;
}
}
}
Запросите страницу About по адресу localhost:5000/About
из примера и посмотрите заголовки, чтобы проверить результат:
Фильтры MVC и фильтр страниц (IPageFilter)
Фильтры действий MVC игнорируются в Razor Pages, так как Razor Pages использует методы обработчиков. Доступны для использования другие типы фильтров MVC: фильтры авторизации, исключений, ресурсов и результатов. Дополнительные сведения см. в разделе Фильтры.
Фильтр страниц (IPageFilter) — это фильтр, применяемый к страницам Razor Pages. Дополнительные сведения см. в разделе Методы фильтрации для Razor Pages.
Дополнительные ресурсы
Узнайте, как использовать соглашения поставщика модели маршрутов и приложений страниц для управления маршрутизацией, обнаружением и обработкой страниц в приложениях Razor Pages.
Когда вам необходимо настроить уникальные маршруты для отдельных страниц, используйте соглашение AddPageRoute, описанное далее в этом разделе.
Чтобы указать маршрут страницы, добавить сегменты маршрута или добавить параметры в маршрут, используйте директиву @page
страницы. Дополнительные сведения см. в разделе Пользовательские маршруты.
Существуют зарезервированные слова, которые нельзя использовать в качестве сегментов маршрутов или имен параметров. Дополнительные сведения см. в статье "Маршрутизация: зарезервированные имена маршрутизации".
Просмотреть или скачать образец кода (описание загрузки)
Сценарий | Что демонстрирует пример |
---|---|
Соглашения для моделей Conventions.Add
|
Добавление шаблона маршрута и заголовка к страницам приложения. |
Соглашения для действий с маршрутами страниц
|
Добавление шаблона маршрута к страницам в папке и к одной странице. |
Соглашения для действий модели страниц
|
Добавление заголовка к страницам в папке, добавление заголовка к одной странице и настройка фабрики фильтров для добавления заголовка к страницам приложения. |
Соглашения Razor Pages добавляются и настраиваются с помощью метода расширения AddRazorPagesOptions в AddMvc в коллекции служб в классе Startup
. Следующие примеры соглашений описаны далее в этом разделе:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc()
.AddRazorPagesOptions(options =>
{
options.Conventions.Add( ... );
options.Conventions.AddFolderRouteModelConvention(
"/OtherPages", model => { ... });
options.Conventions.AddPageRouteModelConvention(
"/About", model => { ... });
options.Conventions.AddPageRoute(
"/Contact", "TheContactPage/{text?}");
options.Conventions.AddFolderApplicationModelConvention(
"/OtherPages", model => { ... });
options.Conventions.AddPageApplicationModelConvention(
"/About", model => { ... });
options.Conventions.ConfigureFilter(model => { ... });
options.Conventions.ConfigureFilter( ... );
});
}
Порядок маршрутов
Для маршрутов указывается свойство Order, определяющее порядок обработки (сопоставления маршрутов).
Порядок | Поведение |
---|---|
-1 | Маршрут обрабатывается до обработки других маршрутов. |
0 | Порядок не задан (значение по умолчанию). Если свойство Order не задано (Order = null ), значение Order по умолчанию для маршрута равно 0 (нулю). |
1, 2, … n | Указывает порядок обработки маршрутов. |
Маршруты обрабатываются в соответствии с соглашением.
- Маршруты обрабатываются по порядку (–1, 0, 1, 2, …, n).
- Если маршруты имеют одинаковые значения свойства
Order
, сначала сопоставляется наиболее конкретный маршрут, а затем более общие. - Если URL-адресу запроса соответствуют маршруты с одинаковым значением свойства
Order
и одинаковым количеством параметров, они обрабатываются в том порядке, в котором были добавлены в коллекцию PageConventionCollection.
По возможности старайтесь не использовать строго определенный порядок обработки маршрутов. Как правило, при маршрутизации правильный маршрут выбирается посредством сопоставления URL-адресов. Если для правильной маршрутизации запросов необходимо задать свойства Order
маршрута, схема маршрутизации приложения, скорее всего, будет малопонятна клиентам и сложна в обслуживании. Старайтесь упростить схему маршрутизации приложения. В примере приложения требуется явно определенный порядок обработки маршрутов для демонстрации нескольких сценариев маршрутизации на основе одного приложения. Однако в рабочих приложениях следует избегать задания свойства Order
для маршрутов.
Средства маршрутизации в Razor Pages и контроллере MVC имеют общую реализацию. Сведения о порядке маршрута в разделах MVC доступны в разделе "Маршрутизация для действий контроллера: упорядочивание маршрутов атрибутов".
Соглашения для моделей
Добавьте делегат для IPageConvention, чтобы добавить соглашения для модели, применяемые к Razor Pages.
Добавление соглашения для модели маршрутов ко всем страницам
Используйте свойство Conventions, чтобы создать и добавить IPageRouteModelConvention в коллекцию экземпляров IPageConvention, которые применяются при формировании модели маршрутов страниц.
В примере приложения шаблон маршрута {globalTemplate?}
добавляется ко всем страницам приложения:
public class GlobalTemplatePageRouteModelConvention
: IPageRouteModelConvention
{
public void Apply(PageRouteModel model)
{
var selectorCount = model.Selectors.Count;
for (var i = 0; i < selectorCount; i++)
{
var selector = model.Selectors[i];
model.Selectors.Add(new SelectorModel
{
AttributeRouteModel = new AttributeRouteModel
{
Order = 1,
Template = AttributeRouteModel.CombineTemplates(
selector.AttributeRouteModel.Template,
"{globalTemplate?}"),
}
});
}
}
}
Свойству Order для AttributeRouteModel задано значение 1
. Это обеспечивает описанное ниже поведение сопоставления маршрутов в примере приложения.
- Шаблон маршрута для
TheContactPage/{text?}
добавляется далее в разделе. Маршрут страницы Contact по умолчанию имеет порядокnull
(Order = 0
), поэтому он сопоставляется до шаблона маршрута{globalTemplate?}
. - Шаблон маршрута
{aboutTemplate?}
добавляется далее в разделе. Шаблону{aboutTemplate?}
задано свойствоOrder
, равное2
. При запросе страницы About по адресу/About/RouteDataValue
значение RouteDataValue загружается вRouteData.Values["globalTemplate"]
(Order = 1
), а не вRouteData.Values["aboutTemplate"]
(Order = 2
). Это происходит из-за значения свойстваOrder
. - Шаблон маршрута
{otherPagesTemplate?}
добавляется далее в разделе. Шаблону{otherPagesTemplate?}
задано свойствоOrder
, равное2
. При запросе любой страницы в папке Pages/OtherPages с параметром маршрута (например,/OtherPages/Page1/RouteDataValue
), RouteDataValue загружается вRouteData.Values["globalTemplate"]
(Order = 1
), а не вRouteData.Values["otherPagesTemplate"]
(Order = 2
). Это происходит из-за значения свойстваOrder
.
По возможности не задавайте свойство Order
, чтобы оно имело значение Order = 0
. Предоставьте системе маршрутизации возможность выбирать правильный маршрут.
Параметры Razor Pages, такие как добавление Conventions, добавляются при добавлении MVC в коллекцию служб в Startup.ConfigureServices
. Пример см. в образце приложения.
options.Conventions.Add(new GlobalTemplatePageRouteModelConvention());
Запросите страницу About по адресу localhost:5000/About/GlobalRouteValue
из примера и проверьте результат:
Добавление соглашения для модели приложений ко всем страницам
Используйте свойство Conventions, чтобы создать и добавить IPageApplicationModelConvention в коллекцию экземпляров IPageConvention, которые применяются при формировании модели приложения страницы.
Для демонстрации этих и других соглашений далее в этом разделе в пример приложения включен класс AddHeaderAttribute
. Конструктор класса принимает строку name
и массив строк values
. Эти значения используются в его методе OnResultExecuting
для задания заголовка ответа. Класс показан полностью в разделе Соглашения для действий модели страниц далее.
Пример приложения использует класс AddHeaderAttribute
, чтобы добавить заголовок GlobalHeader
ко всем страницам в приложении:
public class GlobalHeaderPageApplicationModelConvention
: IPageApplicationModelConvention
{
public void Apply(PageApplicationModel model)
{
model.Filters.Add(new AddHeaderAttribute(
"GlobalHeader", new string[] { "Global Header Value" }));
}
}
Startup.cs
:
options.Conventions.Add(new GlobalHeaderPageApplicationModelConvention());
Запросите страницу About по адресу localhost:5000/About
из примера и посмотрите заголовки, чтобы проверить результат:
Добавление соглашения для модели обработчика ко всем страницам
Используйте свойство Conventions, чтобы создать и добавить IPageHandlerModelConvention в коллекцию экземпляров IPageConvention, которые применяются при формировании модели обработчика страниц.
public class GlobalPageHandlerModelConvention
: IPageHandlerModelConvention
{
public void Apply(PageHandlerModel model)
{
// Access the PageHandlerModel
}
}
Startup.cs
:
options.Conventions.Add(new GlobalPageHandlerModelConvention());
Соглашения для действий с маршрутами страниц
Поставщик модели маршрутов по умолчанию, который является производным от IPageRouteModelProvider, использует соглашения, создающие точки расширения для настройки маршрутов страниц.
Соглашение для модели маршрутов папки
Используйте метод AddFolderRouteModelConvention, чтобы создать и добавить интерфейс IPageRouteModelConvention, вызывающий действие в классе PageRouteModel для всех страниц в указанной папке.
Пример приложения использует AddFolderRouteModelConvention для добавления шаблона маршрута {otherPagesTemplate?}
к страницам в папке OtherPages:
options.Conventions.AddFolderRouteModelConvention("/OtherPages", model =>
{
var selectorCount = model.Selectors.Count;
for (var i = 0; i < selectorCount; i++)
{
var selector = model.Selectors[i];
model.Selectors.Add(new SelectorModel
{
AttributeRouteModel = new AttributeRouteModel
{
Order = 2,
Template = AttributeRouteModel.CombineTemplates(
selector.AttributeRouteModel.Template,
"{otherPagesTemplate?}"),
}
});
}
});
Свойству Order для AttributeRouteModel задано значение 2
. Это гарантирует, что при указании одного значения маршрута приоритетно выбирается значение данных маршрута из шаблона {globalTemplate?}
, которому ранее в разделе было присвоено значение 1
. При запросе страницы в папке Pages/OtherPages со значением параметра маршрута (например, /OtherPages/Page1/RouteDataValue
), RouteDataValue загружается в RouteData.Values["globalTemplate"]
(Order = 1
), а не в RouteData.Values["otherPagesTemplate"]
(Order = 2
). Это происходит из-за значения свойства Order
.
По возможности не задавайте свойство Order
, чтобы оно имело значение Order = 0
. Предоставьте системе маршрутизации возможность выбирать правильный маршрут.
Запросите страницу Page1 по адресу localhost:5000/OtherPages/Page1/GlobalRouteValue/OtherPagesRouteValue
из примера и проверьте результат:
Соглашение для модели маршрутов страницы
Используйте метод AddPageRouteModelConvention, чтобы создать и добавить интерфейс IPageRouteModelConvention, вызывающий действие в классе PageRouteModel для страницы с указанным именем.
Пример приложения использует AddPageRouteModelConvention
для добавления шаблона маршрута {aboutTemplate?}
к странице About:
options.Conventions.AddPageRouteModelConvention("/About", model =>
{
var selectorCount = model.Selectors.Count;
for (var i = 0; i < selectorCount; i++)
{
var selector = model.Selectors[i];
model.Selectors.Add(new SelectorModel
{
AttributeRouteModel = new AttributeRouteModel
{
Order = 2,
Template = AttributeRouteModel.CombineTemplates(
selector.AttributeRouteModel.Template,
"{aboutTemplate?}"),
}
});
}
});
Свойству Order для AttributeRouteModel задано значение 2
. Это гарантирует, что при указании одного значения маршрута приоритетно выбирается значение данных маршрута из шаблона {globalTemplate?}
, которому ранее в разделе было присвоено значение 1
. При запросе страницы About со значением параметра маршрута по адресу /About/RouteDataValue
, RouteDataValue загружается в RouteData.Values["globalTemplate"]
(Order = 1
), а не в RouteData.Values["aboutTemplate"]
(Order = 2
). Это происходит из-за значения свойства Order
.
По возможности не задавайте свойство Order
, чтобы оно имело значение Order = 0
. Предоставьте системе маршрутизации возможность выбирать правильный маршрут.
Запросите страницу About по адресу localhost:5000/About/GlobalRouteValue/AboutRouteValue
из примера и проверьте результат:
Настройка маршрута страницы
Используйте метод AddPageRoute, чтобы настроить маршрут к странице по указанному пути страницы. Созданные ссылки на страницу будут использовать заданный вами маршрут. Для установления маршрута метод AddPageRoute
использует AddPageRouteModelConvention
.
Пример приложения создает маршрут к /TheContactPage
для файла Contact.cshtml
:
options.Conventions.AddPageRoute("/Contact", "TheContactPage/{text?}");
На страницу Contact также можно перейти с помощью /Contact
через маршрут по умолчанию.
Настраиваемый маршрут на страницу Contact в примере приложения позволяет использовать необязательный сегмент маршрута text
({text?}
). Страница также включает этот необязательный сегмент в своей директиве @page
на случай, если посетитель переходит на страницу по маршруту /Contact
:
@page "{text?}"
@model ContactModel
@{
ViewData["Title"] = "Contact";
}
<h1>@ViewData["Title"]</h1>
<h2>@Model.Message</h2>
<address>
One Microsoft Way<br>
Redmond, WA 98052-6399<br>
<abbr title="Phone">P:</abbr>
425.555.0100
</address>
<address>
<strong>Support:</strong> <a href="mailto:Support@example.com">Support@example.com</a><br>
<strong>Marketing:</strong> <a href="mailto:Marketing@example.com">Marketing@example.com</a>
</address>
<p>@Model.RouteDataTextTemplateValue</p>
Обратите внимание, что URL-адрес, созданный для ссылки Contact на отображенной странице, отражает обновленный маршрут:
Перейдите на страницу Contact по ее обычному маршруту /Contact
или по настроенному маршруту /TheContactPage
. Если вы укажете дополнительный сегмент маршрута text
, страница отобразит этот сегмент в HTML-кодировке:
Соглашения для действий модели страниц
Поставщик модели страниц по умолчанию, который реализует IPageApplicationModelProvider, использует соглашения, создающие точки расширения для настройки моделей страниц. Эти соглашения полезны при создании и изменении для обнаружения и обработки страниц.
В примерах этого раздела образец приложения использует класс AddHeaderAttribute
, который является ResultFilterAttribute и применяет заголовок ответа:
public class AddHeaderAttribute : ResultFilterAttribute
{
private readonly string _name;
private readonly string[] _values;
public AddHeaderAttribute(string name, string[] values)
{
_name = name;
_values = values;
}
public override void OnResultExecuting(ResultExecutingContext context)
{
context.HttpContext.Response.Headers.Add(_name, _values);
base.OnResultExecuting(context);
}
}
Образец показывает использование соглашений для применения атрибута ко всем страницам в папке и к одной странице.
Соглашение для модели приложений папки
Используйте метод AddFolderApplicationModelConvention, чтобы создать и добавить интерфейс IPageApplicationModelConvention, вызывающий действие в экземплярах PageApplicationModel для всех страниц в указанной папке.
Пример демонстрирует использование AddFolderApplicationModelConvention
путем добавления заголовка OtherPagesHeader
к страницам в папке OtherPages приложения:
options.Conventions.AddFolderApplicationModelConvention("/OtherPages", model =>
{
model.Filters.Add(new AddHeaderAttribute(
"OtherPagesHeader", new string[] { "OtherPages Header Value" }));
});
Запросите страницу Page1 по адресу localhost:5000/OtherPages/Page1
из примера и посмотрите заголовки, чтобы проверить результат:
Соглашение для модели приложений страницы
Используйте метод AddPageApplicationModelConvention, чтобы создать и добавить интерфейс IPageApplicationModelConvention, вызывающий действие в классе PageApplicationModel для страницы с указанным именем.
Пример демонстрирует использование AddPageApplicationModelConvention
путем добавления заголовка AboutHeader
на страницу About:
options.Conventions.AddPageApplicationModelConvention("/About", model =>
{
model.Filters.Add(new AddHeaderAttribute(
"AboutHeader", new string[] { "About Header Value" }));
});
Запросите страницу About по адресу localhost:5000/About
из примера и посмотрите заголовки, чтобы проверить результат:
Настройка фильтра
Для настройки применяемого фильтра используется метод ConfigureFilter. Вы можете создать класс фильтра, но пример приложения показывает реализацию фильтра в лямбда-выражении, которое реализовано "за кулисами" в качестве фабрики, возвращающей фильтр:
options.Conventions.ConfigureFilter(model =>
{
if (model.RelativePath.Contains("OtherPages/Page2"))
{
return new AddHeaderAttribute(
"OtherPagesPage2Header",
new string[] { "OtherPages/Page2 Header Value" });
}
return new EmptyFilter();
});
Модель приложений страницы используется для проверки относительного пути на наличие сегментов, ведущих к странице Page2 в папке OtherPages. Если условие выполняется, добавляется заголовок. Если нет, применяется EmptyFilter
.
EmptyFilter
является фильтром действий. Так как в Razor Pages фильтры действий не учитываются, EmptyFilter
не оказывает действия, как и задумано, если путь не содержит OtherPages/Page2
.
Запросите страницу Page2 по адресу localhost:5000/OtherPages/Page2
из примера и посмотрите заголовки, чтобы проверить результат:
Настройка фабрики фильтров
Метод ConfigureFilter позволяет настроить указанное производство так, чтобы фильтры применялись ко всем страницам Razor Pages.
В примере приложения приведен образец использования фабрики фильтров путем добавления на страницы приложения заголовка FilterFactoryHeader
с двумя значениями:
options.Conventions.ConfigureFilter(new AddHeaderWithFactory());
AddHeaderWithFactory.cs
:
public class AddHeaderWithFactory : IFilterFactory
{
// Implement IFilterFactory
public IFilterMetadata CreateInstance(IServiceProvider serviceProvider)
{
return new AddHeaderFilter();
}
private class AddHeaderFilter : IResultFilter
{
public void OnResultExecuting(ResultExecutingContext context)
{
context.HttpContext.Response.Headers.Add(
"FilterFactoryHeader",
new string[]
{
"Filter Factory Header Value 1",
"Filter Factory Header Value 2"
});
}
public void OnResultExecuted(ResultExecutedContext context)
{
}
}
public bool IsReusable
{
get
{
return false;
}
}
}
Запросите страницу About по адресу localhost:5000/About
из примера и посмотрите заголовки, чтобы проверить результат:
Фильтры MVC и фильтр страниц (IPageFilter)
Фильтры действий MVC игнорируются в Razor Pages, так как Razor Pages использует методы обработчиков. Доступны для использования другие типы фильтров MVC: фильтры авторизации, исключений, ресурсов и результатов. Дополнительные сведения см. в разделе Фильтры.
Фильтр страниц (IPageFilter) — это фильтр, применяемый к страницам Razor Pages. Дополнительные сведения см. в разделе Методы фильтрации для Razor Pages.
Дополнительные ресурсы
ASP.NET Core