Поделиться через


Razor Соглашения о маршрутах страниц и приложениях в ASP.NET Core

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

Чтобы указать маршрут страницы, добавить сегменты маршрутов или добавить параметры в маршрут, используйте директиву страницы @page . Дополнительные сведения см. в разделе "Пользовательские маршруты".

Есть зарезервированные слова, которые нельзя использовать в качестве сегментов маршрутов или имен параметров. Дополнительные сведения см. в статье "Маршрутизация: зарезервированные имена маршрутизации".

Просмотр или скачивание примера кода (как скачать)

Scenario Пример демонстрирует
Соглашения о модели

Conventions.Add
Добавьте шаблон маршрута и заголовок на страницы приложения.
Конвенции действия маршрута страницы Добавьте шаблон маршрута на страницы в папке и на одну отдельную страницу.
Соглашения об действии модели страницы Добавьте заголовок на страницы в папку, добавьте заголовок на одну страницу и настройте фабрику фильтров для добавления заголовка на страницы приложения.

Razor Конвенции страниц настраиваются с помощью 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 для обработки (сопоставления маршрутов).

Порядок маршрутов Behavior
-1 Маршрут обрабатывается до обработки других маршрутов.
0 Порядок не указан (значение по умолчанию). Если не назначен Order (Order = null), маршрут Order по умолчанию устанавливается на 0 (ноль) для обработки.
1, 2, … n Задает порядок обработки маршрута.

Обработка маршрутов устанавливается по стандарту:

  • Маршруты обрабатываются последовательно (-1, 0, 1, 1, 2, ... n).
  • Если маршруты имеют то же самое Order, то наиболее конкретный маршрут сопоставляется сначала с менее конкретными маршрутами.
  • Если маршруты с одинаковым Order и одинаковым числом параметров соответствуют URL-адресу запроса, маршруты обрабатываются в том порядке, в котором они добавляются PageConventionCollection.

По возможности избегайте зависимости от установленного порядка обработки маршрутов. Как правило, маршрутизация выбирает правильный маршрут с сопоставлением URL-адресов. Если необходимо задать свойства маршрута Order для правильной маршрутизации запросов, схема маршрутизации приложения, вероятно, запутана для клиентов и сложна в поддержке. Стремится упростить схему маршрутизации приложения. Для примера приложения требуется явный порядок обработки маршрутов для демонстрации нескольких сценариев маршрутизации с помощью одного приложения. Однако следует попытаться избежать практики настройки маршрута Order в рабочих приложениях.

Razor Маршрутизация страниц и маршрутизация контроллера 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?}"),
                }
            });
        }
    }
}

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

Razor Параметры страниц, такие как Conventions, добавляются при добавлении Razor страниц в коллекцию служб. Пример см. в примере приложения.

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?} имеет значение Order2. Когда запрашивается страница About по адресу /About/RouteDataValue, "RouteDataValue" загружается в RouteData.Values["globalTemplate"] (Order = 1) и не в RouteData.Values["aboutTemplate"] (Order = 2) из-за установки свойства Order.

  • Шаблон {otherPagesTemplate?} маршрута показан в приведенном выше коде. Шаблон {otherPagesTemplate?} имеет значение Order2. Когда любая страница в папке Pages/OtherPages запрашивается с параметром маршрута:

  • Например: /OtherPages/Page1/xyz

  • Значение данных маршрута "xyz" загружается в RouteData.Values["globalTemplate"] (Order = 1).

  • RouteData.Values["otherPagesTemplate"] с (Order = 2) не загружается из-за свойства Order2, имеющего более высокое значение.

По возможности не устанавливайте 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());

Запросите страницу сведений о образце на 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 и проверьте результат:

Page1 в папке OtherPages запрашивается с сегментом маршрута GlobalRouteValue и OtherPagesRouteValue. На отрисованной странице показано, что значения данных маршрута записываются в методе OnGet страницы.

Конвенция модели маршрутизации страниц

Используйте AddPageRouteModelConvention, чтобы создать и добавить IPageRouteModelConvention, который выполнит действие на PageRouteModel, ассоциированном со страницей с указанным именем.

Пример приложения использует AddPageRouteModelConvention для добавления {aboutTemplate?} шаблона маршрута на страницу "О программе":

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

Запросите страницу localhost:{port}/About/GlobalRouteValue/AboutRouteValue "Сведения о образце" и проверьте результат:

Страница

Выходные данные средства ведения журнала отображаются:

info: SampleApp.Pages.AboutModel[0]
       /About/GlobalRouteValue/AboutRouteValue   Order = 2 Template = About/{globalTemplate?}/{aboutTemplate?}

Использование преобразователя параметров для настройки маршрутов страниц

См. преобразователи параметров.

Настройка маршрута страницы

Используйте AddPageRoute для настройки маршрута к странице по указанному пути. Созданные ссылки на страницу используют указанный маршрут. AddPageRoute используется AddPageRouteModelConvention для установки маршрута.

Пример приложения создает маршрут /TheContactPage для ContactRazor страницы:

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-адрес, созданный для ссылки "Контакт" на отрисованной странице, отражает обновленный маршрут:

Ссылка

Проверка ссылки 'Контакт' в отрисованном HTML указывает, что для href установлено значение

Посетите страницу Contact либо по её обычному маршруту, /Contact, либо по пользовательскому маршруту, /TheContactPage. Если вы предоставляете дополнительный text сегмент маршрута, на странице отображается предоставленный сегмент в кодировке HTML:

Пример браузера Edge для предоставления необязательного сегмента маршрута 'text' в URL-адресе в виде 'TextValue'. На отображаемой странице показано значение сегмента

Соглашения об действии модели страницы

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

Заголовки ответов на странице OtherPages/Page1 показывают, что добавлен объект OtherPagesHeader.

Соглашение о модели приложения страницы

Используйте AddPageApplicationModelConvention, чтобы создать и добавить IPageApplicationModelConvention, который выполнит действие на PageApplicationModel, ассоциированном со страницей с указанным именем.

Пример демонстрирует использование AddPageApplicationModelConvention путем добавления заголовка AboutHeader на страницу "Сведения":

options.Conventions.AddPageApplicationModelConvention("/About", model =>
{
    model.Filters.Add(new AddHeaderAttribute(
        "AboutHeader", new string[] { "About Header Value" }));
});

Запросите страницу сведений о образце на 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, предполагаемый эффект EmptyFilter отсутствует, если путь не содержит OtherPages/Page2.

Запросите страницу Page2 localhost:5000/OtherPages/Page2 примера и проверьте заголовки, чтобы просмотреть результат:

OtherPagesPage2Header добавляется в ответ для Page2.

Настройка фабрики фильтров

ConfigureFilterнастраивает указанную фабрику для применения фильтров ко всем Razorстраницам.

Пример приложения предоставляет пример использования фабрики фильтров путем добавления заголовка с 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;
        }
    }
}

Запросите страницу сведений о образце на localhost:5000/About и проверьте заголовки, чтобы просмотреть результат:

Заголовки ответа на странице

Фильтры MVC и фильтр страницы (IPageFilter)

Фильтры действий MVC игнорируются Razor Страницами, поскольку Razor Страницы используют методы обработчика. Другие типы фильтров MVC доступны для использования: авторизация, исключение, ресурс и результат. Дополнительные сведения см. в разделе "Фильтры ".

Фильтр страниц (IPageFilter) — это фильтр, который применяется к Razor Страницам. Дополнительные сведения см. в разделе Методы фильтрации для Razor Pages.

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

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

Если необходимо настроить маршруты для отдельных страниц, настройте маршрутизацию страниц с помощью соглашения AddPageRoute, описанного далее в этом разделе.

Чтобы указать маршрут страницы, добавить сегменты маршрутов или добавить параметры в маршрут, используйте директиву страницы @page . Дополнительные сведения см. в разделе "Пользовательские маршруты".

Есть зарезервированные слова, которые нельзя использовать в качестве сегментов маршрутов или имен параметров. Дополнительные сведения см. в статье "Маршрутизация: зарезервированные имена маршрутизации".

Просмотр или скачивание примера кода (как скачать)

Scenario Образец демонстрирует ...
Соглашения о модели

Conventions.Add
  • IPageRouteModelConvention
  • IPageApplicationModelConvention
  • IPageHandlerModelConvention
Добавьте шаблон маршрута и заголовок на страницы приложения.
Конвенции действия маршрута страницы
  • AddFolderRouteModelConvention
  • AddPageRouteModelConvention
  • AddPageRoute
Добавьте шаблон маршрута на страницы в папке и на одну отдельную страницу.
Соглашения об действии модели страницы
  • AddFolderApplicationModelConvention
  • AddPageApplicationModelConvention
  • ConfigureFilter (класс фильтра, лямбда-выражение или фабрика фильтров)
Добавьте заголовок на страницы в папку, добавьте заголовок на одну страницу и настройте фабрику фильтров для добавления заголовка на страницы приложения.

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 для обработки (сопоставления маршрутов).

Order Behavior
-1 Маршрут обрабатывается до обработки других маршрутов.
0 Порядок не указан (значение по умолчанию). Если не назначен Order (Order = null), маршрут Order по умолчанию устанавливается на 0 (ноль) для обработки.
1, 2, … n Задает порядок обработки маршрута.

Обработка маршрутов устанавливается по стандарту:

  • Маршруты обрабатываются последовательно (-1, 0, 1, 1, 2, ... n).
  • Если маршруты имеют то же самое Order, то наиболее конкретный маршрут сопоставляется сначала с менее конкретными маршрутами.
  • Если маршруты с одинаковым Order и одинаковым числом параметров соответствуют URL-адресу запроса, маршруты обрабатываются в том порядке, в котором они добавляются PageConventionCollection.

По возможности избегайте зависимости от установленного порядка обработки маршрутов. Как правило, маршрутизация выбирает правильный маршрут с сопоставлением URL-адресов. Если необходимо задать свойства маршрута Order для правильной маршрутизации запросов, схема маршрутизации приложения, вероятно, запутана для клиентов и сложна в поддержке. Стремится упростить схему маршрутизации приложения. Для примера приложения требуется явный порядок обработки маршрутов для демонстрации нескольких сценариев маршрутизации с помощью одного приложения. Однако следует попытаться избежать практики настройки маршрута Order в рабочих приложениях.

Razor Маршрутизация страниц и маршрутизация контроллера 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?} добавляется позже в теме. Маршрут страницы контактов имеет порядок null по умолчанию (Order = 0), поэтому он соответствует перед шаблоном маршрута {globalTemplate?}.
  • Шаблон {aboutTemplate?} маршрута добавляется позже в раздел. Шаблон {aboutTemplate?} имеет значение Order2. Когда запрашивается страница About по адресу /About/RouteDataValue, "RouteDataValue" загружается в RouteData.Values["globalTemplate"] (Order = 1) и не в RouteData.Values["aboutTemplate"] (Order = 2) из-за установки свойства Order.
  • Шаблон {otherPagesTemplate?} маршрута добавляется позже в раздел. Шаблон {otherPagesTemplate?} имеет значение Order2. Если любая страница в папке Pages/OtherPages запрашивается с параметром маршрута (например, /OtherPages/Page1/RouteDataValue), "RouteDataValue" загружается в RouteData.Values["globalTemplate"] (Order = 1), а не в RouteData.Values["otherPagesTemplate"] (Order = 2) вследствие настройки свойства Order.

Если это возможно, не устанавливайте Order, что приводит к Order = 0. Чтобы выбрать правильный маршрут, следует полагаться на маршрутизацию.

RazorПараметры страниц, такие как добавление Conventions, добавляются, когда Razor Pages добавляется в коллекцию служб Startup.ConfigureServices. Пример см. в примере приложения.

options.Conventions.Add(new GlobalTemplatePageRouteModelConvention());

Запросите страницу 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());

Запросите страницу сведений о образце на 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 и проверьте результат:

Page1 в папке OtherPages запрашивается с сегментом маршрута GlobalRouteValue и OtherPagesRouteValue. На отрисованной странице показано, что значения данных маршрута записываются в методе OnGet страницы.

Конвенция модели маршрутизации страниц

Используйте AddPageRouteModelConvention, чтобы создать и добавить IPageRouteModelConvention, который выполнит действие на PageRouteModel, ассоциированном со страницей с указанным именем.

Пример приложения использует AddPageRouteModelConvention для добавления {aboutTemplate?} шаблона маршрута на страницу "О программе":

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

Запросите страницу localhost:5000/About/GlobalRouteValue/AboutRouteValue "Сведения о образце" и проверьте результат:

Страница

Использование преобразователя параметров для настройки маршрутов страниц

Маршруты страниц, созданные ASP.NET Core, можно настроить с помощью преобразователя параметров. Преобразователь параметров реализует IOutboundParameterTransformer и преобразует значения параметров. Например, настраиваемый преобразователь параметров SlugifyParameterTransformer изменяет значение маршрута SubscriptionManagement на subscription-management.

Соглашение PageRouteTransformerConvention о модели маршрутов страницы применяет преобразователь параметров к сегментам папок и имен файлов автоматически созданных маршрутов страниц в приложении. Например, файл Pages по адресу Razor будет переписан маршрут с /Pages/SubscriptionManagement/ViewAll.cshtml на /SubscriptionManagement/ViewAll.

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();
    }
}

Warning

При использовании System.Text.RegularExpressions для обработки ненадежных входных данных передайте время ожидания. Злонамеренный пользователь может предоставить входные данные для RegularExpressions, что делает возможными атаки типа "отказ в обслуживании". API платформы ASP.NET Core, использующие RegularExpressions, передают время ожидания.

Настройка маршрута страницы

Используйте AddPageRoute для настройки маршрута к странице по указанному пути. Созданные ссылки на страницу используют указанный маршрут. AddPageRoute используется AddPageRouteModelConvention для установки маршрута.

Пример приложения создает маршрут к /TheContactPage для Contact.cshtml:

options.Conventions.AddPageRoute("/Contact", "TheContactPage/{text?}");

Страницу контакты также можно открыть /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-адрес, созданный для ссылки "Контакт" на отрисованной странице, отражает обновленный маршрут:

Ссылка

Проверка ссылки 'Контакт' в отрисованном HTML указывает, что для href установлено значение

Посетите страницу "Контакт" либо по его обычному маршруту, /Contactлибо по пользовательскому маршруту. /TheContactPage Если вы предоставляете дополнительный text сегмент маршрута, на странице отображается предоставленный сегмент в кодировке HTML:

Пример браузера Edge для предоставления необязательного сегмента маршрута 'text' в URL-адресе в виде 'TextValue'. На отображаемой странице показано значение сегмента

Соглашения об действии модели страницы

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

Заголовки ответов на странице OtherPages/Page1 показывают, что добавлен объект OtherPagesHeader.

Соглашение о модели приложения страницы

Используйте AddPageApplicationModelConvention, чтобы создать и добавить IPageApplicationModelConvention, который выполнит действие на PageApplicationModel, ассоциированном со страницей с указанным именем.

Пример демонстрирует использование AddPageApplicationModelConvention путем добавления заголовка AboutHeader на страницу "Сведения":

options.Conventions.AddPageApplicationModelConvention("/About", model =>
{
    model.Filters.Add(new AddHeaderAttribute(
        "AboutHeader", new string[] { "About Header Value" }));
});

Запросите страницу сведений о образце на 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, предполагаемый эффект EmptyFilter отсутствует, если путь не содержит OtherPages/Page2.

Запросите страницу Page2 localhost:5000/OtherPages/Page2 примера и проверьте заголовки, чтобы просмотреть результат:

OtherPagesPage2Header добавляется в ответ для Page2.

Настройка фабрики фильтров

ConfigureFilterнастраивает указанную фабрику для применения фильтров ко всем Razorстраницам.

Пример приложения предоставляет пример использования фабрики фильтров путем добавления заголовка с 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;
        }
    }
}

Запросите страницу сведений о образце на localhost:5000/About и проверьте заголовки, чтобы просмотреть результат:

Заголовки ответа на странице

Фильтры MVC и фильтр страницы (IPageFilter)

Фильтры действий MVC игнорируются Razor Страницами, поскольку Razor Страницы используют методы обработчика. Другие типы фильтров MVC доступны для использования: авторизация, исключение, ресурс и результат. Дополнительные сведения см. в разделе "Фильтры ".

Фильтр страниц (IPageFilter) — это фильтр, который применяется к Razor Страницам. Дополнительные сведения см. в разделе Методы фильтрации для Razor Pages.

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

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

Если необходимо настроить маршруты для отдельных страниц, настройте маршрутизацию страниц с помощью соглашения AddPageRoute, описанного далее в этом разделе.

Чтобы указать маршрут страницы, добавить сегменты маршрутов или добавить параметры в маршрут, используйте директиву страницы @page . Дополнительные сведения см. в разделе "Пользовательские маршруты".

Есть зарезервированные слова, которые нельзя использовать в качестве сегментов маршрутов или имен параметров. Дополнительные сведения см. в статье "Маршрутизация: зарезервированные имена маршрутизации".

Просмотр или скачивание примера кода (как скачать)

Scenario Образец демонстрирует ...
Соглашения о модели

Conventions.Add
  • IPageRouteModelConvention
  • IPageApplicationModelConvention
  • IPageHandlerModelConvention
Добавьте шаблон маршрута и заголовок на страницы приложения.
Конвенции действия маршрута страницы
  • AddFolderRouteModelConvention
  • AddPageRouteModelConvention
  • AddPageRoute
Добавьте шаблон маршрута на страницы в папке и на одну отдельную страницу.
Соглашения об действии модели страницы
  • AddFolderApplicationModelConvention
  • AddPageApplicationModelConvention
  • ConfigureFilter (класс фильтра, лямбда-выражение или фабрика фильтров)
Добавьте заголовок на страницы в папку, добавьте заголовок на одну страницу и настройте фабрику фильтров для добавления заголовка на страницы приложения.

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 для обработки (сопоставления маршрутов).

Order Behavior
-1 Маршрут обрабатывается до обработки других маршрутов.
0 Порядок не указан (значение по умолчанию). Если не назначен Order (Order = null), маршрут Order по умолчанию устанавливается на 0 (ноль) для обработки.
1, 2, … n Задает порядок обработки маршрута.

Обработка маршрутов устанавливается по стандарту:

  • Маршруты обрабатываются последовательно (-1, 0, 1, 1, 2, ... n).
  • Если маршруты имеют то же самое Order, то наиболее конкретный маршрут сопоставляется сначала с менее конкретными маршрутами.
  • Если маршруты с одинаковым Order и одинаковым числом параметров соответствуют URL-адресу запроса, маршруты обрабатываются в том порядке, в котором они добавляются PageConventionCollection.

По возможности избегайте зависимости от установленного порядка обработки маршрутов. Как правило, маршрутизация выбирает правильный маршрут с сопоставлением URL-адресов. Если необходимо задать свойства маршрута Order для правильной маршрутизации запросов, схема маршрутизации приложения, вероятно, запутана для клиентов и сложна в поддержке. Стремится упростить схему маршрутизации приложения. Для примера приложения требуется явный порядок обработки маршрутов для демонстрации нескольких сценариев маршрутизации с помощью одного приложения. Однако следует попытаться избежать практики настройки маршрута Order в рабочих приложениях.

Razor Маршрутизация страниц и маршрутизация контроллера 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?} добавляется позже в теме. Маршрут страницы контактов имеет порядок null по умолчанию (Order = 0), поэтому он соответствует перед шаблоном маршрута {globalTemplate?}.
  • Шаблон {aboutTemplate?} маршрута добавляется позже в раздел. Шаблон {aboutTemplate?} имеет значение Order2. Когда запрашивается страница About по адресу /About/RouteDataValue, "RouteDataValue" загружается в RouteData.Values["globalTemplate"] (Order = 1) и не в RouteData.Values["aboutTemplate"] (Order = 2) из-за установки свойства Order.
  • Шаблон {otherPagesTemplate?} маршрута добавляется позже в раздел. Шаблон {otherPagesTemplate?} имеет значение Order2. Если любая страница в папке Pages/OtherPages запрашивается с параметром маршрута (например, /OtherPages/Page1/RouteDataValue), "RouteDataValue" загружается в RouteData.Values["globalTemplate"] (Order = 1), а не в RouteData.Values["otherPagesTemplate"] (Order = 2) вследствие настройки свойства Order.

Если это возможно, не устанавливайте Order, что приводит к Order = 0. Чтобы выбрать правильный маршрут, следует полагаться на маршрутизацию.

RazorПараметры страниц, например добавлениеConventions, добавляются при добавлении MVC в коллекцию служб.Startup.ConfigureServices Пример см. в примере приложения.

options.Conventions.Add(new GlobalTemplatePageRouteModelConvention());

Запросите страницу 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());

Запросите страницу сведений о образце на 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 и проверьте результат:

Page1 в папке OtherPages запрашивается с сегментом маршрута GlobalRouteValue и OtherPagesRouteValue. На отрисованной странице показано, что значения данных маршрута записываются в методе OnGet страницы.

Конвенция модели маршрутизации страниц

Используйте AddPageRouteModelConvention, чтобы создать и добавить IPageRouteModelConvention, который выполнит действие на PageRouteModel, ассоциированном со страницей с указанным именем.

Пример приложения использует AddPageRouteModelConvention для добавления {aboutTemplate?} шаблона маршрута на страницу "О программе":

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

Запросите страницу localhost:5000/About/GlobalRouteValue/AboutRouteValue "Сведения о образце" и проверьте результат:

Страница

Настройка маршрута страницы

Используйте AddPageRoute для настройки маршрута к странице по указанному пути. Созданные ссылки на страницу используют указанный маршрут. AddPageRoute используется AddPageRouteModelConvention для установки маршрута.

Пример приложения создает маршрут к /TheContactPage для Contact.cshtml:

options.Conventions.AddPageRoute("/Contact", "TheContactPage/{text?}");

Страницу контакты также можно открыть /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-адрес, созданный для ссылки "Контакт" на отрисованной странице, отражает обновленный маршрут:

Ссылка

Проверка ссылки 'Контакт' в отрисованном HTML указывает, что для href установлено значение

Посетите страницу "Контакт" либо по его обычному маршруту, /Contactлибо по пользовательскому маршруту. /TheContactPage Если вы предоставляете дополнительный text сегмент маршрута, на странице отображается предоставленный сегмент в кодировке HTML:

Пример браузера Edge для предоставления необязательного сегмента маршрута 'text' в URL-адресе в виде 'TextValue'. На отображаемой странице показано значение сегмента

Соглашения об действии модели страницы

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

Заголовки ответов на странице OtherPages/Page1 показывают, что добавлен объект OtherPagesHeader.

Соглашение о модели приложения страницы

Используйте AddPageApplicationModelConvention, чтобы создать и добавить IPageApplicationModelConvention, который выполнит действие на PageApplicationModel, ассоциированном со страницей с указанным именем.

Пример демонстрирует использование AddPageApplicationModelConvention путем добавления заголовка AboutHeader на страницу "Сведения":

options.Conventions.AddPageApplicationModelConvention("/About", model =>
{
    model.Filters.Add(new AddHeaderAttribute(
        "AboutHeader", new string[] { "About Header Value" }));
});

Запросите страницу сведений о образце на 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, предполагаемый эффект EmptyFilter отсутствует, если путь не содержит OtherPages/Page2.

Запросите страницу Page2 localhost:5000/OtherPages/Page2 примера и проверьте заголовки, чтобы просмотреть результат:

OtherPagesPage2Header добавляется в ответ для Page2.

Настройка фабрики фильтров

ConfigureFilterнастраивает указанную фабрику для применения фильтров ко всем Razorстраницам.

Пример приложения предоставляет пример использования фабрики фильтров путем добавления заголовка с 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;
        }
    }
}

Запросите страницу сведений о образце на localhost:5000/About и проверьте заголовки, чтобы просмотреть результат:

Заголовки ответа на странице

Фильтры MVC и фильтр страницы (IPageFilter)

Фильтры действий MVC игнорируются Razor Страницами, поскольку Razor Страницы используют методы обработчика. Другие типы фильтров MVC доступны для использования: авторизация, исключение, ресурс и результат. Дополнительные сведения см. в разделе "Фильтры ".

Фильтр страниц (IPageFilter) — это фильтр, который применяется к Razor Страницам. Дополнительные сведения см. в разделе Методы фильтрации для Razor Pages.

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