ASP.NET Core 中 Razor 页面的路由和应用约定Razor Pages route and app conventions in ASP.NET Core

作者:Luke LathamBy Luke Latham

了解如何使用页面路由和应用模型提供程序约定来控制 Razor 页面应用中的页面路由、发现和处理。Learn how to use page route and app model provider conventions to control page routing, discovery, and processing in Razor Pages apps.

需要为各个页面配置自定义页面路由时,可使用本主题稍后所述的 AddPageRoute 约定配置页面路由。When you need to configure custom page routes for individual pages, configure routing to pages with the AddPageRoute convention described later in this topic.

若要指定页路由、添加路由段或向路由添加参数,请使用页的 @page 指令。To specify a page route, add route segments, or add parameters to a route, use the page's @page directive. 有关详细信息,请参阅自定义路由For more information, see Custom routes.

有些保留字不能用作路由段或参数名称。There are reserved words that can't be used as route segments or parameter names. 有关详细信息,请参阅路由:保留的路由名称For more information, see Routing: Reserved routing names.

查看或下载示例代码如何下载View or download sample code (how to download)

方案Scenario 示例演示...The sample demonstrates ...
模型约定Model conventions

Conventions.AddConventions.Add
  • IPageRouteModelConventionIPageRouteModelConvention
  • IPageApplicationModelConventionIPageApplicationModelConvention
  • IPageHandlerModelConventionIPageHandlerModelConvention
将路由模板和标头添加到应用的页面。Add a route template and header to an app's pages.
页面路由操作约定Page route action conventions
  • AddFolderRouteModelConventionAddFolderRouteModelConvention
  • AddPageRouteModelConventionAddPageRouteModelConvention
  • AddPageRouteAddPageRoute
将路由模板添加到某个文件夹中的页面以及单个页面。Add a route template to pages in a folder and to a single page.
页面模型操作约定Page model action conventions
  • AddFolderApplicationModelConventionAddFolderApplicationModelConvention
  • AddPageApplicationModelConventionAddPageApplicationModelConvention
  • ConfigureFilter(筛选器类、Lambda 表达式或筛选器工厂)ConfigureFilter (filter class, lambda expression, or filter factory)
将标头添加到某个文件夹中的多个页面,将标头添加到单个页面,以及配置筛选器工厂以将标头添加到应用的页面。Add a header to pages in a folder, add a header to a single page, and configure a filter factory to add a header to an app's pages.

使用 AddRazorPagesOptions 扩展方法添加和配置 Razor Pages 约定,以 AddMvc Startup 类中的服务集合。Razor Pages conventions are added and configured using the AddRazorPagesOptions extension method to AddMvc on the service collection in the Startup class. 本主题稍后会介绍以下约定示例:The following convention examples are explained later in this topic:

public void ConfigureServices(IServiceCollection services)
{
    services.AddRazorPages()
        .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( ... );
        });
}
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( ... );
        });
}

路由顺序Route order

路由指定了用于处理的 Order (路由匹配)。Routes specify an Order for processing (route matching).

顺序Order 行为Behavior
-1-1 在处理其他路由之前处理路由。The route is processed before other routes are processed.
00 未指定顺序(默认值)。Order isn't specified (default value). 不分配 OrderOrder = null)默认情况下,路由 Order 为0(零)以进行处理。Not assigning Order (Order = null) defaults the route Order to 0 (zero) for processing.
1,2,… n1, 2, … n 指定路由处理顺序。Specifies the route processing order.

按约定建立路由处理:Route processing is established by convention:

  • 按顺序处理路由(-1、0、1、2、… n)。Routes are processed in sequential order (-1, 0, 1, 2, … n).
  • 当路由具有相同的 Order 时,首先匹配最具体的路由,然后匹配不太具体的路由。When routes have the same Order, the most specific route is matched first followed by less specific routes.
  • 当具有相同 Order 和相同数量参数的路由匹配请求 URL 时,路由将按照它们添加到 PageConventionCollection 的顺序进行处理。When routes with the same Order and the same number of parameters match a request URL, routes are processed in the order that they're added to the PageConventionCollection.

如果可能,请避免依赖于建立的路由处理顺序。If possible, avoid depending on an established route processing order. 通常,路由将选择 URL 匹配的正确路由。Generally, routing selects the correct route with URL matching. 如果必须将路由 Order 属性设置为正确路由请求,则应用的路由方案可能会使客户端混乱,并使其保持脆弱。If you must set route Order properties to route requests correctly, the app's routing scheme is probably confusing to clients and fragile to maintain. 设法简化应用的路由方案。Seek to simplify the app's routing scheme. 该示例应用需要显式路由处理顺序才能使用单个应用来演示几个路由方案。The sample app requires an explicit route processing order to demonstrate several routing scenarios using a single app. 但是,你应尝试避免在生产应用中设置路由 Order 的做法。However, you should attempt to avoid the practice of setting route Order in production apps.

Razor Pages 路由和 MVC 控制器路由共享一个实现。Razor Pages routing and MVC controller routing share an implementation. 有关 MVC 主题中的路由顺序的信息,请参阅路由到控制器操作:排序属性路由Information on route order in the MVC topics is available at Routing to controller actions: Ordering attribute routes.

模型约定Model conventions

IPageConvention 添加一个委托,以便添加适用于 Razor Pages 的模型约定Add a delegate for IPageConvention to add model conventions that apply to Razor Pages.

向所有页面添加路由模型约定Add a route model convention to all pages

使用 Conventions 创建 IPageRouteModelConvention,并将其添加到在页路由模型构造期间应用的 IPageConvention 实例的集合。Use Conventions to create and add an IPageRouteModelConvention to the collection of IPageConvention instances that are applied during page route model construction.

示例应用将 {globalTemplate?} 路由模板添加到应用中的所有页面:The sample app adds a {globalTemplate?} route template to all of the pages in the app:

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?}"),
                }
            });
        }
    }
}
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?}"),
                }
            });
        }
    }
}

AttributeRouteModelOrder 属性设置为 1The Order property for the AttributeRouteModel is set to 1. 这可确保示例应用中的以下路由匹配行为:This ensures the following route matching behavior in the sample app:

  • 本主题稍后会添加 TheContactPage/{text?} 的路由模板。A route template for TheContactPage/{text?} is added later in the topic. 联系人页路由的默认顺序为 nullOrder = 0),因此它在 {globalTemplate?} 路由模板之前匹配。The Contact Page route has a default order of null (Order = 0), so it matches before the {globalTemplate?} route template.
  • 本主题稍后会添加一个 {aboutTemplate?} 的路由模板。An {aboutTemplate?} route template is added later in the topic. {aboutTemplate?} 模板指定的 Order2The {aboutTemplate?} template is given an Order of 2. 当在 /About/RouteDataValue 中请求“关于”页面时,由于设置了 Order 属性,“RouteDataValue”会加载到 RouteData.Values["globalTemplate"] (Order = 1) 而不是 RouteData.Values["aboutTemplate"] (Order = 2) 中。When the About page is requested at /About/RouteDataValue, "RouteDataValue" is loaded into RouteData.Values["globalTemplate"] (Order = 1) and not RouteData.Values["aboutTemplate"] (Order = 2) due to setting the Order property.
  • 本主题稍后会添加一个 {otherPagesTemplate?} 的路由模板。An {otherPagesTemplate?} route template is added later in the topic. {otherPagesTemplate?} 模板指定的 Order2The {otherPagesTemplate?} template is given an Order of 2. 当使用路由参数(例如 /OtherPages/Page1/RouteDataValue)请求Pages/OtherPages文件夹中的任何页面时,将 "RouteDataValue" 加载到 RouteData.Values["globalTemplate"]Order = 1),而不是 RouteData.Values["otherPagesTemplate"]Order = 2),因为设置 Order 属性。When any page in the Pages/OtherPages folder is requested with a route parameter (for example, /OtherPages/Page1/RouteDataValue), "RouteDataValue" is loaded into RouteData.Values["globalTemplate"] (Order = 1) and not RouteData.Values["otherPagesTemplate"] (Order = 2) due to setting the Order property.

请尽可能不要将 Order 设置为 Order = 0Wherever possible, don't set the Order, which results in Order = 0. 依赖 "路由" 选择正确的路由。Rely on routing to select the correct route.

将 MVC 添加到 Startup.ConfigureServices 中的服务集合时,会添加 Razor Pages 选项,如添加 ConventionsRazor Pages options, such as adding Conventions, are added when MVC is added to the service collection in Startup.ConfigureServices. 有关示例,请参阅示例应用For an example, see the sample app.

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

localhost:5000/About/GlobalRouteValue 中请求示例的“关于”页面并检查结果:Request the sample's About page at localhost:5000/About/GlobalRouteValue and inspect the result:

使用 GlobalRouteValue 路由段请求“关于”页面。

将应用模型约定添加到所有页面Add an app model convention to all pages

使用 Conventions 创建 IPageApplicationModelConvention,并将其添加到在页面应用模式构造期间应用的 IPageConvention 实例的集合。Use Conventions to create and add an IPageApplicationModelConvention to the collection of IPageConvention instances that are applied during page app model construction.

为了演示此约定以及本主题后面的其他约定,示例应用包含了一个 AddHeaderAttribute 类。To demonstrate this and other conventions later in the topic, the sample app includes an AddHeaderAttribute class. 类构造函数采用 name 字符串和 values 字符串数组。The class constructor accepts a name string and a values string array. 将在其 OnResultExecuting 方法中使用这些值来设置响应标头。These values are used in its OnResultExecuting method to set a response header. 本主题后面的页面模型操作约定部分展示了完整的类。The full class is shown in the Page model action conventions section later in the topic.

示例应用使用 AddHeaderAttribute 类将标头 GlobalHeader 添加到应用中的所有页面:The sample app uses the AddHeaderAttribute class to add a header, GlobalHeader, to all of the pages in the app:

public class GlobalHeaderPageApplicationModelConvention 
    : IPageApplicationModelConvention
{
    public void Apply(PageApplicationModel model)
    {
        model.Filters.Add(new AddHeaderAttribute(
            "GlobalHeader", new string[] { "Global Header Value" }));
    }
}
public class GlobalHeaderPageApplicationModelConvention 
    : IPageApplicationModelConvention
{
    public void Apply(PageApplicationModel model)
    {
        model.Filters.Add(new AddHeaderAttribute(
            "GlobalHeader", new string[] { "Global Header Value" }));
    }
}

Startup.csStartup.cs:

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

localhost:5000/About 中请求示例的“关于”页面,并检查标头以查看结果:Request the sample's About page at localhost:5000/About and inspect the headers to view the result:

“关于”页面的响应标头显示已添加 GlobalHeader。

将处理程序模型约定添加到所有页面Add a handler model convention to all pages

使用 Conventions 创建 IPageHandlerModelConvention,并将其添加到在页处理程序模型构造期间应用的 IPageConvention 实例的集合。Use Conventions to create and add an IPageHandlerModelConvention to the collection of IPageConvention instances that are applied during page handler model construction.

public class GlobalPageHandlerModelConvention
    : IPageHandlerModelConvention
{
    public void Apply(PageHandlerModel model)
    {
        // Access the PageHandlerModel
    }
}
public class GlobalPageHandlerModelConvention
    : IPageHandlerModelConvention
{
    public void Apply(PageHandlerModel model)
    {
        // Access the PageHandlerModel
    }
}

Startup.csStartup.cs:

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

页面路由操作约定Page route action conventions

派生自 IPageRouteModelProvider 的默认路由模型提供程序调用用于提供扩展点以配置页面路由的约定。The default route model provider that derives from IPageRouteModelProvider invokes conventions which are designed to provide extensibility points for configuring page routes.

文件夹路由模型约定Folder route model convention

使用 AddFolderRouteModelConvention 来创建和添加 IPageRouteModelConvention,该可对指定文件夹下的所有页面调用 PageRouteModel 上的操作。Use AddFolderRouteModelConvention to create and add an IPageRouteModelConvention that invokes an action on the PageRouteModel for all of the pages under the specified folder.

示例应用使用 AddFolderRouteModelConvention{otherPagesTemplate?} 路由模板添加到 OtherPages 文件夹中的页面:The sample app uses AddFolderRouteModelConvention to add an {otherPagesTemplate?} route template to the pages in the OtherPages folder:

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.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?}"),
            }
        });
    }
});

AttributeRouteModelOrder 属性设置为 2The Order property for the AttributeRouteModel is set to 2. 这可确保在提供单个路由值时,将 {globalTemplate?} 的模板(在主题中设置为 1)被授予第一个路由数据值位置的优先级。This ensures that the template for {globalTemplate?} (set earlier in the topic to 1) is given priority for the first route data value position when a single route value is provided. 如果使用路由参数值(例如 /OtherPages/Page1/RouteDataValue)请求Pages/OtherPages文件夹中的页,则将 "RouteDataValue" 加载到 RouteData.Values["globalTemplate"]Order = 1),而不是 RouteData.Values["otherPagesTemplate"]Order = 2),因为设置 Order 属性。If a page in the Pages/OtherPages folder is requested with a route parameter value (for example, /OtherPages/Page1/RouteDataValue), "RouteDataValue" is loaded into RouteData.Values["globalTemplate"] (Order = 1) and not RouteData.Values["otherPagesTemplate"] (Order = 2) due to setting the Order property.

请尽可能不要将 Order 设置为 Order = 0Wherever possible, don't set the Order, which results in Order = 0. 依赖 "路由" 选择正确的路由。Rely on routing to select the correct route.

localhost:5000/OtherPages/Page1/GlobalRouteValue/OtherPagesRouteValue 中请求示例的 Page1 页面并检查结果:Request the sample's Page1 page at localhost:5000/OtherPages/Page1/GlobalRouteValue/OtherPagesRouteValue and inspect the result:

使用 GlobalRouteValue 和 OtherPagesRouteValue 路由段请求 OtherPages 文件夹中的 Page1。

页面路由模型约定Page route model convention

使用 AddPageRouteModelConvention 创建和添加 IPageRouteModelConvention,该在具有指定名称的页的 PageRouteModel 上调用操作。Use AddPageRouteModelConvention to create and add an IPageRouteModelConvention that invokes an action on the PageRouteModel for the page with the specified name.

示例应用使用 AddPageRouteModelConvention{aboutTemplate?} 路由模板添加到“关于”页面:The sample app uses AddPageRouteModelConvention to add an {aboutTemplate?} route template to the About page:

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?}"),
            }
        });
    }
});
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?}"),
            }
        });
    }
});

AttributeRouteModelOrder 属性设置为 2The Order property for the AttributeRouteModel is set to 2. 这可确保在提供单个路由值时,将 {globalTemplate?} 的模板(在主题中设置为 1)被授予第一个路由数据值位置的优先级。This ensures that the template for {globalTemplate?} (set earlier in the topic to 1) is given priority for the first route data value position when a single route value is provided. 如果使用 /About/RouteDataValue 的路由参数值请求 "关于" 页,则将 "RouteDataValue" 加载到 RouteData.Values["globalTemplate"]Order = 1),而不是 RouteData.Values["aboutTemplate"]Order = 2),因为设置 Order 属性。If the About page is requested with a route parameter value at /About/RouteDataValue, "RouteDataValue" is loaded into RouteData.Values["globalTemplate"] (Order = 1) and not RouteData.Values["aboutTemplate"] (Order = 2) due to setting the Order property.

请尽可能不要将 Order 设置为 Order = 0Wherever possible, don't set the Order, which results in Order = 0. 依赖 "路由" 选择正确的路由。Rely on routing to select the correct route.

localhost:5000/About/GlobalRouteValue/AboutRouteValue 中请求示例的“关于”页面并检查结果:Request the sample's About page at localhost:5000/About/GlobalRouteValue/AboutRouteValue and inspect the result:

使用 GlobalRouteValue 和 AboutRouteValue 路由段请求“关于”页面。

使用参数转换器自定义页面路由Use a parameter transformer to customize page routes

可以使用参数转换器自定义 ASP.NET Core 生成的页面路由。Page routes generated by ASP.NET Core can be customized using a parameter transformer. 参数转换程序实现 IOutboundParameterTransformer 并转换参数值。A parameter transformer implements IOutboundParameterTransformer and transforms the value of parameters. 例如,一个自定义 SlugifyParameterTransformer 参数转换程序可将 SubscriptionManagement 路由值更改为 subscription-managementFor example, a custom SlugifyParameterTransformer parameter transformer changes the SubscriptionManagement route value to subscription-management.

@No__t_0 页路由模型约定将参数变压器应用到应用中自动生成的页面路由的文件夹和文件名段。The PageRouteTransformerConvention page route model convention applies a parameter transformer to the folder and file name segments of automatically generated page routes in an app. 例如,位于 /Pages/SubscriptionManagement/ViewAll.cshtml的 Razor Pages 文件会将其路由从 /SubscriptionManagement/ViewAll 重写到 /subscription-management/view-all 中。For example, the Razor Pages file at /Pages/SubscriptionManagement/ViewAll.cshtml would have its route rewritten from /SubscriptionManagement/ViewAll to /subscription-management/view-all.

PageRouteTransformerConvention 仅转换来自 Razor Pages 文件夹和文件名的自动生成的页面路由段。PageRouteTransformerConvention only transforms the automatically generated segments of a page route that come from the Razor Pages folder and file name. 它不会转换添加了 @page 指令的路由段。It doesn't transform route segments added with the @page directive. 该约定还不会转换 AddPageRoute 添加的路由。The convention also doesn't transform routes added by AddPageRoute.

@No__t_0 注册为 Startup.ConfigureServices 中的一个选项:The PageRouteTransformerConvention is registered as an option in Startup.ConfigureServices:

public void ConfigureServices(IServiceCollection services)
{
    services.AddRazorPages()
        .AddRazorPagesOptions(options =>
        {
            options.Conventions.Add(
                new PageRouteTransformerConvention(
                    new SlugifyParameterTransformer()));
        });
}

public class SlugifyParameterTransformer : IOutboundParameterTransformer
{
    public string TransformOutbound(object value)
    {
        if (value == null) { return null; }

        // Slugify value
        return Regex.Replace(value.ToString(), "([a-z])([A-Z])", "$1-$2").ToLower();
    }
}
public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc()
        .AddRazorPagesOptions(options =>
        {
            options.Conventions.Add(
                new PageRouteTransformerConvention(
                    new SlugifyParameterTransformer()));
        });
}

public class SlugifyParameterTransformer : IOutboundParameterTransformer
{
    public string TransformOutbound(object value)
    {
        if (value == null) { return null; }

        // Slugify value
        return Regex.Replace(value.ToString(), "([a-z])([A-Z])", "$1-$2").ToLower();
    }
}

配置页面路由Configure a page route

使用 AddPageRoute 配置指向指定页面路径中的页面的路由。Use AddPageRoute to configure a route to a page at the specified page path. 生成的页面链接使用指定的路由。Generated links to the page use your specified route. AddPageRoute 使用 AddPageRouteModelConvention 建立路由。AddPageRoute uses AddPageRouteModelConvention to establish the route.

示例应用为 Contact.cshtml 创建指向 /TheContactPage 的路由:The sample app creates a route to /TheContactPage for Contact.cshtml:

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

还可在 /Contact 中通过默认路由访问“联系人”页面。The Contact page can also be reached at /Contact via its default route.

示例应用的“联系人”页面自定义路由允许使用可选的 text 路由段 ({text?})。The sample app's custom route to the Contact page allows for an optional text route segment ({text?}). 该页面还在其 @page 指令中包含此可选段,以便访问者在 /Contact 路由中访问该页面:The page also includes this optional segment in its @page directive in case the visitor accesses the page at its /Contact route:

@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>
@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 反映了已更新的路由:Note that the URL generated for the Contact link in the rendered page reflects the updated route:

导航栏中的示例应用“联系人”链接

检查呈现的 HTML 中的“联系人”链接,可看到 href 设置为“/TheContactPage”

在常规路由 /Contact 或自定义路由 /TheContactPage 中访问“联系人”页面。Visit the Contact page at either its ordinary route, /Contact, or the custom route, /TheContactPage. 如果提供附加的 text 路由段,该页面会显示所提供的 HTML 编码段:If you supply an additional text route segment, the page shows the HTML-encoded segment that you provide:

在 URL 中提供可选“'text”路由段“TextValue”的 Microsoft Edge 浏览器示例。

页面模型操作约定Page model action conventions

实现 IPageApplicationModelProvider 的默认页面模型提供程序调用用于为配置页面模型提供扩展点的约定。The default page model provider that implements IPageApplicationModelProvider invokes conventions which are designed to provide extensibility points for configuring page models. 在生成和修改页面发现及处理方案时,可使用这些约定。These conventions are useful when building and modifying page discovery and processing scenarios.

对于本部分中的示例,示例应用使用 AddHeaderAttribute 类,该类是一个 ResultFilterAttribute,它应用响应标头:For the examples in this section, the sample app uses an AddHeaderAttribute class, which is a ResultFilterAttribute, that applies a response header:

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

示例演示了如何使用约定将该属性应用于某个文件夹中的所有页面以及单个页面。Using conventions, the sample demonstrates how to apply the attribute to all of the pages in a folder and to a single page.

文件夹应用模型约定Folder app model convention

使用 AddFolderApplicationModelConvention 创建和添加 IPageApplicationModelConvention,该在指定文件夹下的所有页面的 PageApplicationModel 实例上调用操作。Use AddFolderApplicationModelConvention to create and add an IPageApplicationModelConvention that invokes an action on PageApplicationModel instances for all pages under the specified folder.

示例演示了如何使用 AddFolderApplicationModelConvention 将标头 OtherPagesHeader 添加到应用的 OtherPages 文件夹内的页面:The sample demonstrates the use of AddFolderApplicationModelConvention by adding a header, OtherPagesHeader, to the pages inside the OtherPages folder of the app:

options.Conventions.AddFolderApplicationModelConvention("/OtherPages", model =>
{
    model.Filters.Add(new AddHeaderAttribute(
        "OtherPagesHeader", new string[] { "OtherPages Header Value" }));
});
options.Conventions.AddFolderApplicationModelConvention("/OtherPages", model =>
{
    model.Filters.Add(new AddHeaderAttribute(
        "OtherPagesHeader", new string[] { "OtherPages Header Value" }));
});

localhost:5000/OtherPages/Page1 中请求示例的 Page1 页面,并检查标头以查看结果:Request the sample's Page1 page at localhost:5000/OtherPages/Page1 and inspect the headers to view the result:

OtherPages/Page1 页面的响应标头显示已添加 OtherPagesHeader。

页面应用模型约定Page app model convention

使用 AddPageApplicationModelConvention 创建和添加 IPageApplicationModelConvention,该在具有指定名称的页的 PageApplicationModel 上调用操作。Use AddPageApplicationModelConvention to create and add an IPageApplicationModelConvention that invokes an action on the PageApplicationModel for the page with the specified name.

示例演示了如何使用 AddPageApplicationModelConvention 将标头 AboutHeader 添加到“关于”页面:The sample demonstrates the use of AddPageApplicationModelConvention by adding a header, AboutHeader, to the About page:

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

localhost:5000/About 中请求示例的“关于”页面,并检查标头以查看结果:Request the sample's About page at localhost:5000/About and inspect the headers to view the result:

“关于”页面的响应标头显示已添加 AboutHeader。

配置筛选器Configure a filter

ConfigureFilter 配置要应用的指定筛选器。ConfigureFilter configures the specified filter to apply. 用户可以实现筛选器类,但示例应用演示了如何在 Lambda 表达式中实现筛选器,该筛选器在后台作为可返回筛选器的工厂实现:You can implement a filter class, but the sample app shows how to implement a filter in a lambda expression, which is implemented behind-the-scenes as a factory that returns a filter:

options.Conventions.ConfigureFilter(model =>
{
    if (model.RelativePath.Contains("OtherPages/Page2"))
    {
        return new AddHeaderAttribute(
            "OtherPagesPage2Header", 
            new string[] { "OtherPages/Page2 Header Value" });
    }
    return new EmptyFilter();
});
options.Conventions.ConfigureFilter(model =>
{
    if (model.RelativePath.Contains("OtherPages/Page2"))
    {
        return new AddHeaderAttribute(
            "OtherPagesPage2Header", 
            new string[] { "OtherPages/Page2 Header Value" });
    }
    return new EmptyFilter();
});

页面应用模型用于检查指向 OtherPages 文件夹中 Page2 页面的段的相对路径。The page app model is used to check the relative path for segments that lead to the Page2 page in the OtherPages folder. 如果条件通过,则添加标头。If the condition passes, a header is added. 如果不通过,则应用 EmptyFilterIf not, the EmptyFilter is applied.

EmptyFilter 是一种操作筛选器EmptyFilter is an Action filter. 由于 Razor Pages 忽略操作筛选器,因此,如果路径不包含 OtherPages/Page2,则 EmptyFilter 不起作用。Since Action filters are ignored by Razor Pages, the EmptyFilter has no effect as intended if the path doesn't contain OtherPages/Page2.

localhost:5000/OtherPages/Page2 中请求示例的 Page2 页面,并检查标头以查看结果:Request the sample's Page2 page at localhost:5000/OtherPages/Page2 and inspect the headers to view the result:

OtherPagesPage2Header 已添加到 Page2 的响应。

配置筛选器工厂Configure a filter factory

ConfigureFilter 配置指定工厂,以将筛选器应用于所有 Razor Pages。ConfigureFilter configures the specified factory to apply filters to all Razor Pages.

示例应用提供了一个示例,说明如何使用筛选器工厂将具有两个值的标头 FilterFactoryHeader 添加到应用的页面:The sample app provides an example of using a filter factory by adding a header, FilterFactoryHeader, with two values to the app's pages:

options.Conventions.ConfigureFilter(new AddHeaderWithFactory());
options.Conventions.ConfigureFilter(new AddHeaderWithFactory());

AddHeaderWithFactory.csAddHeaderWithFactory.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;
        }
    }
}
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 中请求示例的“关于”页面,并检查标头以查看结果:Request the sample's About page at localhost:5000/About and inspect the headers to view the result:

“关于”页面的响应标头显示已添加两个 FilterFactoryHeader 标头。

MVC 筛选器和页面筛选器 (IPageFilter)MVC Filters and the Page filter (IPageFilter)

Razor 页面会忽略 MVC 操作筛选器,因为 Razor 页面使用处理程序方法。MVC Action filters are ignored by Razor Pages, since Razor Pages use handler methods. 可使用其他类型的 MVC 筛选器:授权异常资源结果Other types of MVC filters are available for you to use: Authorization, Exception, Resource, and Result. 有关详细信息,请参阅筛选器主题。For more information, see the Filters topic.

页面筛选器(IPageFilter)是应用于 Razor Pages 的筛选器。The Page filter (IPageFilter) is a filter that applies to Razor Pages. 有关详细信息,请参阅 Razor 页面的筛选方法For more information, see Filter methods for Razor Pages.

其他资源Additional resources