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

本文内容

了解如何使用页面路由和应用模型提供程序约定来控制 Razor 页面应用中的页面路由、发现和处理。

需要为各个页面配置自定义页面路由时,可使用本主题稍后所述的 AddPageRoute 约定配置页面路由。

若要指定页面路由、添加路由段或向路由添加参数,请使用页面的 @page 指令。有关详细信息,请参阅自定义路由

有些保留字不能用作路由段或参数名称。有关详细信息,请参阅路由:保留的路由名称

查看或下载示例代码如何下载

方案示例演示…
模型约定Conventions.Add

- IPageRouteModelConvention
- IPageApplicationModelConvention
- IPageHandlerModelConvention
将路由模板和标头添加到应用的页面。
页面路由操作约定

- AddFolderRouteModelConvention
- AddPageRouteModelConvention
- AddPageRoute
将路由模板添加到某个文件夹中的页面以及单个页面。
页面模型操作约定

- AddFolderApplicationModelConvention
- AddPageApplicationModelConvention
- ConfigureFilter(筛选器类、Lambda 表达式或筛选器工厂)
将标头添加到某个文件夹中的多个页面,将标头添加到单个页面,以及配置筛选器工厂以将标头添加到应用的页面。

使用 AddRazorPagesOptions 扩展方法向 Startup 类中服务集合的 AddMvc 添加和配置 Razor Pages 约定。本主题稍后会介绍以下约定示例:

  1. public void ConfigureServices(IServiceCollection services)
  2. {
  3. services.AddRazorPages()
  4. .AddRazorPagesOptions(options =>
  5. {
  6. options.Conventions.Add( ... );
  7. options.Conventions.AddFolderRouteModelConvention(
  8. "/OtherPages", model => { ... });
  9. options.Conventions.AddPageRouteModelConvention(
  10. "/About", model => { ... });
  11. options.Conventions.AddPageRoute(
  12. "/Contact", "TheContactPage/{text?}");
  13. options.Conventions.AddFolderApplicationModelConvention(
  14. "/OtherPages", model => { ... });
  15. options.Conventions.AddPageApplicationModelConvention(
  16. "/About", model => { ... });
  17. options.Conventions.ConfigureFilter(model => { ... });
  18. options.Conventions.ConfigureFilter( ... );
  19. });
  20. }

路由顺序Route order

路由会为进行处理指定一个 Order(路由匹配)。

顺序行为
-1在处理其他路由之前处理该路由。
0未指定顺序(默认值)。不分配 Order (Order = null) 会将路由 Order 默认为 0(零)以进行处理。
1、2 … n指定路由处理顺序。

按约定建立路由处理:

  • 按顺序处理路由(-1、0、1、2 … n)。
  • 当路由具有相同 Order 时,首先匹配最具体的路由,然后匹配不太具体的路由。
  • 当具有相同 Order 和相同数量参数的路由与请求 URL 匹配时,会按添加到 PageConventionCollection 的顺序处理路由。

如果可能,请避免依赖于建立的路由处理顺序。通常,路由会通过 URL 匹配选择正确路由。如果必须设置路由 Order 属性以便正确路由请求,则应用的路由方案可能会使客户端感到困惑并且难以维护。应设法简化应用的路由方案。示例应用需要显式路由处理顺序以使用单个应用来演示几个路由方案。但是,在生产应用中应尝试避免设置路由 Order 的做法。

Razor Pages 路由和 MVC 控制器路由共享一个实现。有关 MVC 主题中的路由顺序的信息可在以下位置获得:路由到控制器操作:对属性路由排序

模型约定Model conventions

IPageConvention 添加委托,以添加应用于 Razor Pages 的模型约定

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

使用 Conventions 创建 IPageRouteModelConvention 并将其添加到 IPageConvention 实例集合中,这些实例将在页面路由模型构造过程中应用。

示例应用将 {globalTemplate?} 路由模板添加到应用中的所有页面:

  1. public class GlobalTemplatePageRouteModelConvention
  2. : IPageRouteModelConvention
  3. {
  4. public void Apply(PageRouteModel model)
  5. {
  6. var selectorCount = model.Selectors.Count;
  7. for (var i = 0; i < selectorCount; i++)
  8. {
  9. var selector = model.Selectors[i];
  10. model.Selectors.Add(new SelectorModel
  11. {
  12. AttributeRouteModel = new AttributeRouteModel
  13. {
  14. Order = 1,
  15. Template = AttributeRouteModel.CombineTemplates(
  16. selector.AttributeRouteModel.Template,
  17. "{globalTemplate?}"),
  18. }
  19. });
  20. }
  21. }
  22. }

AttributeRouteModelOrder 属性设置为 1这可确保在示例应用中实现以下路由匹配行为:

  • 本主题后面会添加 TheContactPage/{text?} 的路由模板。“联系人”页面路由具有默认顺序 null (Order = 0),因此它在 {globalTemplate?} 路由模板之前进行匹配。
  • 本主题后面会添加 {aboutTemplate?} 路由模板。为 {aboutTemplate?} 模板指定的 Order2。当在 /About/RouteDataValue 中请求“关于”页面时,由于设置了 Order 属性,“RouteDataValue”会加载到 RouteData.Values["globalTemplate"] (Order = 1) 而不是 RouteData.Values["aboutTemplate"] (Order = 2) 中。
  • 本主题后面会添加 {otherPagesTemplate?} 路由模板。为 {otherPagesTemplate?} 模板指定的 Order2。当使用路由参数请求 Pages/OtherPages 文件夹中的任何页面(例如,/OtherPages/Page1/RouteDataValue)时,由于设置了 Order 属性,因此“RouteDataValue”会加载到 RouteData.Values["globalTemplate"] (Order = 1) 中,而不是 RouteData.Values["otherPagesTemplate"] (Order = 2) 中。

尽可能不要将 Order 设置为 Order = 0依赖路由选择正确的路由。

将 MVC 添加到 Startup.ConfigureServices 中的服务集合时,会添加 Razor Pages 选项,例如添加 Conventions有关示例,请参阅示例应用

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

localhost:5000/About/GlobalRouteValue 中请求示例的“关于”页面并检查结果:

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

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

使用 Conventions 创建 IPageApplicationModelConvention 并将其添加到 IPageConvention 实例集合中,这些实例将在页面应用模型构造过程中应用。

为了演示此约定以及本主题后面的其他约定,示例应用包含了一个 AddHeaderAttribute 类。类构造函数采用 name 字符串和 values 字符串数组。将在其 OnResultExecuting 方法中使用这些值来设置响应标头。本主题后面的页面模型操作约定部分展示了完整的类。

示例应用使用 AddHeaderAttribute 类将标头 GlobalHeader 添加到应用中的所有页面:

  1. public class GlobalHeaderPageApplicationModelConvention
  2. : IPageApplicationModelConvention
  3. {
  4. public void Apply(PageApplicationModel model)
  5. {
  6. model.Filters.Add(new AddHeaderAttribute(
  7. "GlobalHeader", new string[] { "Global Header Value" }));
  8. }
  9. }

Startup.cs

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

localhost:5000/About 中请求示例的“关于”页面,并检查标头以查看结果:

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

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

使用 Conventions 创建 IPageHandlerModelConvention 并将其添加到 IPageConvention 实例集合中,这些实例将在页面处理程序模型构造过程中应用。

  1. public class GlobalPageHandlerModelConvention
  2. : IPageHandlerModelConvention
  3. {
  4. public void Apply(PageHandlerModel model)
  5. {
  6. // Access the PageHandlerModel
  7. }
  8. }

Startup.cs

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

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

默认路由模型提供程序派生自 IPageRouteModelProvider,可调用旨在为页面路由配置提供扩展点的约定。

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

使用 AddFolderRouteModelConvention 可创建和添加 IPageRouteModelConvention,它对于指定文件夹下的所有页面,会在 PageRouteModel 上调用操作。

示例应用使用 AddFolderRouteModelConvention{otherPagesTemplate?} 路由模板添加到 OtherPages 文件夹中的页面:

  1. options.Conventions.AddFolderRouteModelConvention("/OtherPages", model =>
  2. {
  3. var selectorCount = model.Selectors.Count;
  4. for (var i = 0; i < selectorCount; i++)
  5. {
  6. var selector = model.Selectors[i];
  7. model.Selectors.Add(new SelectorModel
  8. {
  9. AttributeRouteModel = new AttributeRouteModel
  10. {
  11. Order = 2,
  12. Template = AttributeRouteModel.CombineTemplates(
  13. selector.AttributeRouteModel.Template,
  14. "{otherPagesTemplate?}"),
  15. }
  16. });
  17. }
  18. });

AttributeRouteModelOrder 属性设置为 2这样可确保,当提供单个路由值时,优先将 {globalTemplate?} 的模板(已在本主题的前面部分设置为 1)作为第一个路由数据值位置。如果使用路由参数值请求 Pages/OtherPages 文件夹中的任何页面(例如,/OtherPages/Page1/RouteDataValue)时,由于设置了 Order 属性,因此“RouteDataValue”会加载到 RouteData.Values["globalTemplate"] (Order = 1) 中,而不是 RouteData.Values["otherPagesTemplate"] (Order = 2) 中。

尽可能不要将 Order 设置为 Order = 0依赖路由选择正确的路由。

localhost:5000/OtherPages/Page1/GlobalRouteValue/OtherPagesRouteValue 中请求示例的 Page1 页面并检查结果:

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

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

使用 AddPageRouteModelConvention 可创建和添加 IPageRouteModelConvention,它对于具有指定名称的页面,会在 PageRouteModel 上调用操作。

示例应用使用 AddPageRouteModelConvention{aboutTemplate?} 路由模板添加到“关于”页面:

  1. options.Conventions.AddPageRouteModelConvention("/About", model =>
  2. {
  3. var selectorCount = model.Selectors.Count;
  4. for (var i = 0; i < selectorCount; i++)
  5. {
  6. var selector = model.Selectors[i];
  7. model.Selectors.Add(new SelectorModel
  8. {
  9. AttributeRouteModel = new AttributeRouteModel
  10. {
  11. Order = 2,
  12. Template = AttributeRouteModel.CombineTemplates(
  13. selector.AttributeRouteModel.Template,
  14. "{aboutTemplate?}"),
  15. }
  16. });
  17. }
  18. });

AttributeRouteModelOrder 属性设置为 2这样可确保,当提供单个路由值时,优先将 {globalTemplate?} 的模板(已在本主题的前面部分设置为 1)作为第一个路由数据值位置。如果在 /About/RouteDataValue 中使用路由参数值请求“关于”页面,由于设置了 Order 属性,“RouteDataValue”会加载到 RouteData.Values["globalTemplate"] (Order = 1) 而不是 RouteData.Values["aboutTemplate"] (Order = 2) 中。

尽可能不要将 Order 设置为 Order = 0依赖路由选择正确的路由。

localhost:5000/About/GlobalRouteValue/AboutRouteValue 中请求示例的“关于”页面并检查结果:

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

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

可以使用参数转换程序自定义 ASP.NET Core 生成的页面路由。参数转换程序实现 IOutboundParameterTransformer 并转换参数值。例如,一个自定义 SlugifyParameterTransformer 参数转换程序可将 SubscriptionManagement 路由值更改为 subscription-management

PageRouteTransformerConvention 页面路由模型约定将参数转换程序应用于应用中自动生成的页面路由的文件夹和文件名段。例如,/Pages/SubscriptionManagement/ViewAll.cshtml 处的 Razor Pages 文件会将其路由从 /SubscriptionManagement/ViewAll 重写为 /subscription-management/view-all

PageRouteTransformerConvention 仅转换来自 Razor Pages 文件夹和文件名的自动生成页面路由段。它不会转换使用 @page 指令添加的路由段。该约定也不会转换 AddPageRoute 添加的路由。

PageRouteTransformerConventionStartup.ConfigureServices 中注册为选项:

  1. public void ConfigureServices(IServiceCollection services)
  2. {
  3. services.AddRazorPages()
  4. .AddRazorPagesOptions(options =>
  5. {
  6. options.Conventions.Add(
  7. new PageRouteTransformerConvention(
  8. new SlugifyParameterTransformer()));
  9. });
  10. }
  11. public class SlugifyParameterTransformer : IOutboundParameterTransformer
  12. {
  13. public string TransformOutbound(object value)
  14. {
  15. if (value == null) { return null; }
  16. // Slugify value
  17. return Regex.Replace(value.ToString(), "([a-z])([A-Z])", "$1-$2").ToLower();
  18. }
  19. }

配置页面路由Configure a page route

使用 AddPageRoute 配置路由,该路由指向指定页面路径中的页面。生成的页面链接使用指定的路由。AddPageRoute 使用 AddPageRouteModelConvention 建立路由。

示例应用为 Contact.cshtml 创建指向 /TheContactPage 的路由:

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

还可在 /Contact 中通过默认路由访问“联系人”页面。

示例应用的“联系人”页面自定义路由允许使用可选的 text 路由段 ({text?})。该页面还在其 @page 指令中包含此可选段,以便访问者在 /Contact 路由中访问该页面:

  1. @page "{text?}"
  2. @model ContactModel
  3. @{
  4. ViewData["Title"] = "Contact";
  5. }
  6. <h1>@ViewData["Title"]</h1>
  7. <h2>@Model.Message</h2>
  8. <address>
  9. One Microsoft Way<br>
  10. Redmond, WA 98052-6399<br>
  11. <abbr title="Phone">P:</abbr>
  12. 425.555.0100
  13. </address>
  14. <address>
  15. <strong>Support:</strong> <a href="mailto:Support@example.com">Support@example.com</a><br>
  16. <strong>Marketing:</strong> <a href="mailto:Marketing@example.com">Marketing@example.com</a>
  17. </address>
  18. <p>@Model.RouteDataTextTemplateValue</p>

请注意,在呈现的页面中,为联系人链接生成的 URL 反映了已更新的路由:

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

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

在常规路由 /Contact 或自定义路由 /TheContactPage 中访问“联系人”页面。如果提供附加的 text 路由段,该页面会显示所提供的 HTML 编码段:

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

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

实现 IPageApplicationModelProvider 的默认页面模型提供程序可调用约定,这些约定旨在为页面模型配置提供扩展点。在生成和修改页面发现及处理方案时,可使用这些约定。

对于此部分中的示例,示例应用使用 AddHeaderAttribute 类(一个 ResultFilterAttribute)来应用响应标头:

  1. public class AddHeaderAttribute : ResultFilterAttribute
  2. {
  3. private readonly string _name;
  4. private readonly string[] _values;
  5. public AddHeaderAttribute(string name, string[] values)
  6. {
  7. _name = name;
  8. _values = values;
  9. }
  10. public override void OnResultExecuting(ResultExecutingContext context)
  11. {
  12. context.HttpContext.Response.Headers.Add(_name, _values);
  13. base.OnResultExecuting(context);
  14. }
  15. }

示例演示了如何使用约定将该属性应用于某个文件夹中的所有页面以及单个页面。

文件夹应用模型约定

使用 AddFolderApplicationModelConvention 可创建和添加 IPageApplicationModelConvention,它对于指定文件夹下的所有页面,会在 PageApplicationModel 实例上调用操作。

示例演示了如何使用 AddFolderApplicationModelConvention 将标头 OtherPagesHeader 添加到应用的 OtherPages 文件夹内的页面:

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

localhost:5000/OtherPages/Page1 中请求示例的 Page1 页面,并检查标头以查看结果:

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

页面应用模型约定

使用 AddPageApplicationModelConvention 可创建和添加 IPageApplicationModelConvention,它对于具有指定名称的页面,会在 PageApplicationModel 上调用操作。

示例演示了如何使用 AddPageApplicationModelConvention 将标头 AboutHeader 添加到“关于”页面:

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

localhost:5000/About 中请求示例的“关于”页面,并检查标头以查看结果:

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

配置筛选器

ConfigureFilter 可配置要应用的指定筛选器。用户可以实现筛选器类,但示例应用演示了如何在 Lambda 表达式中实现筛选器,该筛选器在后台作为可返回筛选器的工厂实现:

  1. options.Conventions.ConfigureFilter(model =>
  2. {
  3. if (model.RelativePath.Contains("OtherPages/Page2"))
  4. {
  5. return new AddHeaderAttribute(
  6. "OtherPagesPage2Header",
  7. new string[] { "OtherPages/Page2 Header Value" });
  8. }
  9. return new EmptyFilter();
  10. });

页面应用模型用于检查指向 OtherPages 文件夹中 Page2 页面的段的相对路径。如果条件通过,则添加标头。如果不通过,则应用 EmptyFilter

EmptyFilter 是一种操作筛选器由于 Razor Pages 会忽略操作筛选器,因此,如果路径不包含 OtherPages/Page2EmptyFilter 会按预期没有影响。

localhost:5000/OtherPages/Page2 中请求示例的 Page2 页面,并检查标头以查看结果:

OtherPagesPage2Header 已添加到 Page2 的响应。

配置筛选器工厂

ConfigureFilter 可配置指定的工厂,以将筛选器应用于所有 Razor Pages。

示例应用提供了一个示例,说明如何使用筛选器工厂将具有两个值的标头 FilterFactoryHeader 添加到应用的页面:

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

AddHeaderWithFactory.cs

  1. public class AddHeaderWithFactory : IFilterFactory
  2. {
  3. // Implement IFilterFactory
  4. public IFilterMetadata CreateInstance(IServiceProvider serviceProvider)
  5. {
  6. return new AddHeaderFilter();
  7. }
  8. private class AddHeaderFilter : IResultFilter
  9. {
  10. public void OnResultExecuting(ResultExecutingContext context)
  11. {
  12. context.HttpContext.Response.Headers.Add(
  13. "FilterFactoryHeader",
  14. new string[]
  15. {
  16. "Filter Factory Header Value 1",
  17. "Filter Factory Header Value 2"
  18. });
  19. }
  20. public void OnResultExecuted(ResultExecutedContext context)
  21. {
  22. }
  23. }
  24. public bool IsReusable
  25. {
  26. get
  27. {
  28. return false;
  29. }
  30. }
  31. }

localhost:5000/About 中请求示例的“关于”页面,并检查标头以查看结果:

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

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

Razor 页面会忽略 MVC 操作筛选器,因为 Razor 页面使用处理程序方法。可以使用其他类型的 MVC 筛选器:授权异常资源结果有关详细信息,请参阅筛选器主题。

页面筛选器 (IPageFilter) 是应用于 Razor Pages 的一种筛选器。有关详细信息,请参阅 Razor 页面的筛选方法

其他资源Additional resources

了解如何使用页面路由和应用模型提供程序约定来控制 Razor 页面应用中的页面路由、发现和处理。

需要为各个页面配置自定义页面路由时,可使用本主题稍后所述的 AddPageRoute 约定配置页面路由。

若要指定页面路由、添加路由段或向路由添加参数,请使用页面的 @page 指令。有关详细信息,请参阅自定义路由

有些保留字不能用作路由段或参数名称。有关详细信息,请参阅路由:保留的路由名称

查看或下载示例代码如何下载

方案示例演示…
模型约定Conventions.Add

- IPageRouteModelConvention
- IPageApplicationModelConvention
- IPageHandlerModelConvention
将路由模板和标头添加到应用的页面。
页面路由操作约定

- AddFolderRouteModelConvention
- AddPageRouteModelConvention
- AddPageRoute
将路由模板添加到某个文件夹中的页面以及单个页面。
页面模型操作约定

- AddFolderApplicationModelConvention
- AddPageApplicationModelConvention
- ConfigureFilter(筛选器类、Lambda 表达式或筛选器工厂)
将标头添加到某个文件夹中的多个页面,将标头添加到单个页面,以及配置筛选器工厂以将标头添加到应用的页面。

使用 AddRazorPagesOptions 扩展方法向 Startup 类中服务集合的 AddMvc 添加和配置 Razor Pages 约定。本主题稍后会介绍以下约定示例:

  1. public void ConfigureServices(IServiceCollection services)
  2. {
  3. services.AddMvc()
  4. .AddRazorPagesOptions(options =>
  5. {
  6. options.Conventions.Add( ... );
  7. options.Conventions.AddFolderRouteModelConvention(
  8. "/OtherPages", model => { ... });
  9. options.Conventions.AddPageRouteModelConvention(
  10. "/About", model => { ... });
  11. options.Conventions.AddPageRoute(
  12. "/Contact", "TheContactPage/{text?}");
  13. options.Conventions.AddFolderApplicationModelConvention(
  14. "/OtherPages", model => { ... });
  15. options.Conventions.AddPageApplicationModelConvention(
  16. "/About", model => { ... });
  17. options.Conventions.ConfigureFilter(model => { ... });
  18. options.Conventions.ConfigureFilter( ... );
  19. });
  20. }

路由顺序Route order

路由会为进行处理指定一个 Order(路由匹配)。

顺序行为
-1在处理其他路由之前处理该路由。
0未指定顺序(默认值)。不分配 Order (Order = null) 会将路由 Order 默认为 0(零)以进行处理。
1、2 … n指定路由处理顺序。

按约定建立路由处理:

  • 按顺序处理路由(-1、0、1、2 … n)。
  • 当路由具有相同 Order 时,首先匹配最具体的路由,然后匹配不太具体的路由。
  • 当具有相同 Order 和相同数量参数的路由与请求 URL 匹配时,会按添加到 PageConventionCollection 的顺序处理路由。

如果可能,请避免依赖于建立的路由处理顺序。通常,路由会通过 URL 匹配选择正确路由。如果必须设置路由 Order 属性以便正确路由请求,则应用的路由方案可能会使客户端感到困惑并且难以维护。应设法简化应用的路由方案。示例应用需要显式路由处理顺序以使用单个应用来演示几个路由方案。但是,在生产应用中应尝试避免设置路由 Order 的做法。

Razor Pages 路由和 MVC 控制器路由共享一个实现。有关 MVC 主题中的路由顺序的信息可在以下位置获得:路由到控制器操作:对属性路由排序

模型约定Model conventions

IPageConvention 添加委托,以添加应用于 Razor Pages 的模型约定

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

使用 Conventions 创建 IPageRouteModelConvention 并将其添加到 IPageConvention 实例集合中,这些实例将在页面路由模型构造过程中应用。

示例应用将 {globalTemplate?} 路由模板添加到应用中的所有页面:

  1. public class GlobalTemplatePageRouteModelConvention
  2. : IPageRouteModelConvention
  3. {
  4. public void Apply(PageRouteModel model)
  5. {
  6. var selectorCount = model.Selectors.Count;
  7. for (var i = 0; i < selectorCount; i++)
  8. {
  9. var selector = model.Selectors[i];
  10. model.Selectors.Add(new SelectorModel
  11. {
  12. AttributeRouteModel = new AttributeRouteModel
  13. {
  14. Order = 1,
  15. Template = AttributeRouteModel.CombineTemplates(
  16. selector.AttributeRouteModel.Template,
  17. "{globalTemplate?}"),
  18. }
  19. });
  20. }
  21. }
  22. }

AttributeRouteModelOrder 属性设置为 1这可确保在示例应用中实现以下路由匹配行为:

  • 本主题后面会添加 TheContactPage/{text?} 的路由模板。“联系人”页面路由具有默认顺序 null (Order = 0),因此它在 {globalTemplate?} 路由模板之前进行匹配。
  • 本主题后面会添加 {aboutTemplate?} 路由模板。为 {aboutTemplate?} 模板指定的 Order2。当在 /About/RouteDataValue 中请求“关于”页面时,由于设置了 Order 属性,“RouteDataValue”会加载到 RouteData.Values["globalTemplate"] (Order = 1) 而不是 RouteData.Values["aboutTemplate"] (Order = 2) 中。
  • 本主题后面会添加 {otherPagesTemplate?} 路由模板。为 {otherPagesTemplate?} 模板指定的 Order2。当使用路由参数请求 Pages/OtherPages 文件夹中的任何页面(例如,/OtherPages/Page1/RouteDataValue)时,由于设置了 Order 属性,因此“RouteDataValue”会加载到 RouteData.Values["globalTemplate"] (Order = 1) 中,而不是 RouteData.Values["otherPagesTemplate"] (Order = 2) 中。

尽可能不要将 Order 设置为 Order = 0依赖路由选择正确的路由。

将 MVC 添加到 Startup.ConfigureServices 中的服务集合时,会添加 Razor Pages 选项,例如添加 Conventions有关示例,请参阅示例应用

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

localhost:5000/About/GlobalRouteValue 中请求示例的“关于”页面并检查结果:

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

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

使用 Conventions 创建 IPageApplicationModelConvention 并将其添加到 IPageConvention 实例集合中,这些实例将在页面应用模型构造过程中应用。

为了演示此约定以及本主题后面的其他约定,示例应用包含了一个 AddHeaderAttribute 类。类构造函数采用 name 字符串和 values 字符串数组。将在其 OnResultExecuting 方法中使用这些值来设置响应标头。本主题后面的页面模型操作约定部分展示了完整的类。

示例应用使用 AddHeaderAttribute 类将标头 GlobalHeader 添加到应用中的所有页面:

  1. public class GlobalHeaderPageApplicationModelConvention
  2. : IPageApplicationModelConvention
  3. {
  4. public void Apply(PageApplicationModel model)
  5. {
  6. model.Filters.Add(new AddHeaderAttribute(
  7. "GlobalHeader", new string[] { "Global Header Value" }));
  8. }
  9. }

Startup.cs

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

localhost:5000/About 中请求示例的“关于”页面,并检查标头以查看结果:

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

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

使用 Conventions 创建 IPageHandlerModelConvention 并将其添加到 IPageConvention 实例集合中,这些实例将在页面处理程序模型构造过程中应用。

  1. public class GlobalPageHandlerModelConvention
  2. : IPageHandlerModelConvention
  3. {
  4. public void Apply(PageHandlerModel model)
  5. {
  6. // Access the PageHandlerModel
  7. }
  8. }

Startup.cs

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

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

默认路由模型提供程序派生自 IPageRouteModelProvider,可调用旨在为页面路由配置提供扩展点的约定。

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

使用 AddFolderRouteModelConvention 可创建和添加 IPageRouteModelConvention,它对于指定文件夹下的所有页面,会在 PageRouteModel 上调用操作。

示例应用使用 AddFolderRouteModelConvention{otherPagesTemplate?} 路由模板添加到 OtherPages 文件夹中的页面:

  1. options.Conventions.AddFolderRouteModelConvention("/OtherPages", model =>
  2. {
  3. var selectorCount = model.Selectors.Count;
  4. for (var i = 0; i < selectorCount; i++)
  5. {
  6. var selector = model.Selectors[i];
  7. model.Selectors.Add(new SelectorModel
  8. {
  9. AttributeRouteModel = new AttributeRouteModel
  10. {
  11. Order = 2,
  12. Template = AttributeRouteModel.CombineTemplates(
  13. selector.AttributeRouteModel.Template,
  14. "{otherPagesTemplate?}"),
  15. }
  16. });
  17. }
  18. });

AttributeRouteModelOrder 属性设置为 2这样可确保,当提供单个路由值时,优先将 {globalTemplate?} 的模板(已在本主题的前面部分设置为 1)作为第一个路由数据值位置。如果使用路由参数值请求 Pages/OtherPages 文件夹中的任何页面(例如,/OtherPages/Page1/RouteDataValue)时,由于设置了 Order 属性,因此“RouteDataValue”会加载到 RouteData.Values["globalTemplate"] (Order = 1) 中,而不是 RouteData.Values["otherPagesTemplate"] (Order = 2) 中。

尽可能不要将 Order 设置为 Order = 0依赖路由选择正确的路由。

localhost:5000/OtherPages/Page1/GlobalRouteValue/OtherPagesRouteValue 中请求示例的 Page1 页面并检查结果:

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

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

使用 AddPageRouteModelConvention 可创建和添加 IPageRouteModelConvention,它对于具有指定名称的页面,会在 PageRouteModel 上调用操作。

示例应用使用 AddPageRouteModelConvention{aboutTemplate?} 路由模板添加到“关于”页面:

  1. options.Conventions.AddPageRouteModelConvention("/About", model =>
  2. {
  3. var selectorCount = model.Selectors.Count;
  4. for (var i = 0; i < selectorCount; i++)
  5. {
  6. var selector = model.Selectors[i];
  7. model.Selectors.Add(new SelectorModel
  8. {
  9. AttributeRouteModel = new AttributeRouteModel
  10. {
  11. Order = 2,
  12. Template = AttributeRouteModel.CombineTemplates(
  13. selector.AttributeRouteModel.Template,
  14. "{aboutTemplate?}"),
  15. }
  16. });
  17. }
  18. });

AttributeRouteModelOrder 属性设置为 2这样可确保,当提供单个路由值时,优先将 {globalTemplate?} 的模板(已在本主题的前面部分设置为 1)作为第一个路由数据值位置。如果在 /About/RouteDataValue 中使用路由参数值请求“关于”页面,由于设置了 Order 属性,“RouteDataValue”会加载到 RouteData.Values["globalTemplate"] (Order = 1) 而不是 RouteData.Values["aboutTemplate"] (Order = 2) 中。

尽可能不要将 Order 设置为 Order = 0依赖路由选择正确的路由。

localhost:5000/About/GlobalRouteValue/AboutRouteValue 中请求示例的“关于”页面并检查结果:

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

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

可以使用参数转换程序自定义 ASP.NET Core 生成的页面路由。参数转换程序实现 IOutboundParameterTransformer 并转换参数值。例如,一个自定义 SlugifyParameterTransformer 参数转换程序可将 SubscriptionManagement 路由值更改为 subscription-management

PageRouteTransformerConvention 页面路由模型约定将参数转换程序应用于应用中自动生成的页面路由的文件夹和文件名段。例如,/Pages/SubscriptionManagement/ViewAll.cshtml 处的 Razor Pages 文件会将其路由从 /SubscriptionManagement/ViewAll 重写为 /subscription-management/view-all

PageRouteTransformerConvention 仅转换来自 Razor Pages 文件夹和文件名的自动生成页面路由段。它不会转换使用 @page 指令添加的路由段。该约定也不会转换 AddPageRoute 添加的路由。

PageRouteTransformerConventionStartup.ConfigureServices 中注册为选项:

  1. public void ConfigureServices(IServiceCollection services)
  2. {
  3. services.AddMvc()
  4. .AddRazorPagesOptions(options =>
  5. {
  6. options.Conventions.Add(
  7. new PageRouteTransformerConvention(
  8. new SlugifyParameterTransformer()));
  9. });
  10. }
  11. public class SlugifyParameterTransformer : IOutboundParameterTransformer
  12. {
  13. public string TransformOutbound(object value)
  14. {
  15. if (value == null) { return null; }
  16. // Slugify value
  17. return Regex.Replace(value.ToString(), "([a-z])([A-Z])", "$1-$2").ToLower();
  18. }
  19. }

配置页面路由Configure a page route

使用 AddPageRoute 配置路由,该路由指向指定页面路径中的页面。生成的页面链接使用指定的路由。AddPageRoute 使用 AddPageRouteModelConvention 建立路由。

示例应用为 Contact.cshtml 创建指向 /TheContactPage 的路由:

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

还可在 /Contact 中通过默认路由访问“联系人”页面。

示例应用的“联系人”页面自定义路由允许使用可选的 text 路由段 ({text?})。该页面还在其 @page 指令中包含此可选段,以便访问者在 /Contact 路由中访问该页面:

  1. @page "{text?}"
  2. @model ContactModel
  3. @{
  4. ViewData["Title"] = "Contact";
  5. }
  6. <h1>@ViewData["Title"]</h1>
  7. <h2>@Model.Message</h2>
  8. <address>
  9. One Microsoft Way<br>
  10. Redmond, WA 98052-6399<br>
  11. <abbr title="Phone">P:</abbr>
  12. 425.555.0100
  13. </address>
  14. <address>
  15. <strong>Support:</strong> <a href="mailto:Support@example.com">Support@example.com</a><br>
  16. <strong>Marketing:</strong> <a href="mailto:Marketing@example.com">Marketing@example.com</a>
  17. </address>
  18. <p>@Model.RouteDataTextTemplateValue</p>

请注意,在呈现的页面中,为联系人链接生成的 URL 反映了已更新的路由:

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

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

在常规路由 /Contact 或自定义路由 /TheContactPage 中访问“联系人”页面。如果提供附加的 text 路由段,该页面会显示所提供的 HTML 编码段:

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

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

实现 IPageApplicationModelProvider 的默认页面模型提供程序可调用约定,这些约定旨在为页面模型配置提供扩展点。在生成和修改页面发现及处理方案时,可使用这些约定。

对于此部分中的示例,示例应用使用 AddHeaderAttribute 类(一个 ResultFilterAttribute)来应用响应标头:

  1. public class AddHeaderAttribute : ResultFilterAttribute
  2. {
  3. private readonly string _name;
  4. private readonly string[] _values;
  5. public AddHeaderAttribute(string name, string[] values)
  6. {
  7. _name = name;
  8. _values = values;
  9. }
  10. public override void OnResultExecuting(ResultExecutingContext context)
  11. {
  12. context.HttpContext.Response.Headers.Add(_name, _values);
  13. base.OnResultExecuting(context);
  14. }
  15. }

示例演示了如何使用约定将该属性应用于某个文件夹中的所有页面以及单个页面。

文件夹应用模型约定

使用 AddFolderApplicationModelConvention 可创建和添加 IPageApplicationModelConvention,它对于指定文件夹下的所有页面,会在 PageApplicationModel 实例上调用操作。

示例演示了如何使用 AddFolderApplicationModelConvention 将标头 OtherPagesHeader 添加到应用的 OtherPages 文件夹内的页面:

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

localhost:5000/OtherPages/Page1 中请求示例的 Page1 页面,并检查标头以查看结果:

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

页面应用模型约定

使用 AddPageApplicationModelConvention 可创建和添加 IPageApplicationModelConvention,它对于具有指定名称的页面,会在 PageApplicationModel 上调用操作。

示例演示了如何使用 AddPageApplicationModelConvention 将标头 AboutHeader 添加到“关于”页面:

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

localhost:5000/About 中请求示例的“关于”页面,并检查标头以查看结果:

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

配置筛选器

ConfigureFilter 可配置要应用的指定筛选器。用户可以实现筛选器类,但示例应用演示了如何在 Lambda 表达式中实现筛选器,该筛选器在后台作为可返回筛选器的工厂实现:

  1. options.Conventions.ConfigureFilter(model =>
  2. {
  3. if (model.RelativePath.Contains("OtherPages/Page2"))
  4. {
  5. return new AddHeaderAttribute(
  6. "OtherPagesPage2Header",
  7. new string[] { "OtherPages/Page2 Header Value" });
  8. }
  9. return new EmptyFilter();
  10. });

页面应用模型用于检查指向 OtherPages 文件夹中 Page2 页面的段的相对路径。如果条件通过,则添加标头。如果不通过,则应用 EmptyFilter

EmptyFilter 是一种操作筛选器由于 Razor Pages 会忽略操作筛选器,因此,如果路径不包含 OtherPages/Page2EmptyFilter 会按预期没有影响。

localhost:5000/OtherPages/Page2 中请求示例的 Page2 页面,并检查标头以查看结果:

OtherPagesPage2Header 已添加到 Page2 的响应。

配置筛选器工厂

ConfigureFilter 可配置指定的工厂,以将筛选器应用于所有 Razor Pages。

示例应用提供了一个示例,说明如何使用筛选器工厂将具有两个值的标头 FilterFactoryHeader 添加到应用的页面:

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

AddHeaderWithFactory.cs

  1. public class AddHeaderWithFactory : IFilterFactory
  2. {
  3. // Implement IFilterFactory
  4. public IFilterMetadata CreateInstance(IServiceProvider serviceProvider)
  5. {
  6. return new AddHeaderFilter();
  7. }
  8. private class AddHeaderFilter : IResultFilter
  9. {
  10. public void OnResultExecuting(ResultExecutingContext context)
  11. {
  12. context.HttpContext.Response.Headers.Add(
  13. "FilterFactoryHeader",
  14. new string[]
  15. {
  16. "Filter Factory Header Value 1",
  17. "Filter Factory Header Value 2"
  18. });
  19. }
  20. public void OnResultExecuted(ResultExecutedContext context)
  21. {
  22. }
  23. }
  24. public bool IsReusable
  25. {
  26. get
  27. {
  28. return false;
  29. }
  30. }
  31. }

localhost:5000/About 中请求示例的“关于”页面,并检查标头以查看结果:

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

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

Razor 页面会忽略 MVC 操作筛选器,因为 Razor 页面使用处理程序方法。可以使用其他类型的 MVC 筛选器:授权异常资源结果有关详细信息,请参阅筛选器主题。

页面筛选器 (IPageFilter) 是应用于 Razor Pages 的一种筛选器。有关详细信息,请参阅 Razor 页面的筛选方法

其他资源Additional resources

了解如何使用页面路由和应用模型提供程序约定来控制 Razor 页面应用中的页面路由、发现和处理。

需要为各个页面配置自定义页面路由时,可使用本主题稍后所述的 AddPageRoute 约定配置页面路由。

若要指定页面路由、添加路由段或向路由添加参数,请使用页面的 @page 指令。有关详细信息,请参阅自定义路由

有些保留字不能用作路由段或参数名称。有关详细信息,请参阅路由:保留的路由名称

查看或下载示例代码如何下载

方案示例演示…
模型约定Conventions.Add

- IPageRouteModelConvention
- IPageApplicationModelConvention
- IPageHandlerModelConvention
将路由模板和标头添加到应用的页面。
页面路由操作约定

- AddFolderRouteModelConvention
- AddPageRouteModelConvention
- AddPageRoute
将路由模板添加到某个文件夹中的页面以及单个页面。
页面模型操作约定

- AddFolderApplicationModelConvention
- AddPageApplicationModelConvention
- ConfigureFilter(筛选器类、Lambda 表达式或筛选器工厂)
将标头添加到某个文件夹中的多个页面,将标头添加到单个页面,以及配置筛选器工厂以将标头添加到应用的页面。

使用 AddRazorPagesOptions 扩展方法向 Startup 类中服务集合的 AddMvc 添加和配置 Razor Pages 约定。本主题稍后会介绍以下约定示例:

  1. public void ConfigureServices(IServiceCollection services)
  2. {
  3. services.AddMvc()
  4. .AddRazorPagesOptions(options =>
  5. {
  6. options.Conventions.Add( ... );
  7. options.Conventions.AddFolderRouteModelConvention(
  8. "/OtherPages", model => { ... });
  9. options.Conventions.AddPageRouteModelConvention(
  10. "/About", model => { ... });
  11. options.Conventions.AddPageRoute(
  12. "/Contact", "TheContactPage/{text?}");
  13. options.Conventions.AddFolderApplicationModelConvention(
  14. "/OtherPages", model => { ... });
  15. options.Conventions.AddPageApplicationModelConvention(
  16. "/About", model => { ... });
  17. options.Conventions.ConfigureFilter(model => { ... });
  18. options.Conventions.ConfigureFilter( ... );
  19. });
  20. }

路由顺序Route order

路由会为进行处理指定一个 Order(路由匹配)。

顺序行为
-1在处理其他路由之前处理该路由。
0未指定顺序(默认值)。不分配 Order (Order = null) 会将路由 Order 默认为 0(零)以进行处理。
1、2 … n指定路由处理顺序。

按约定建立路由处理:

  • 按顺序处理路由(-1、0、1、2 … n)。
  • 当路由具有相同 Order 时,首先匹配最具体的路由,然后匹配不太具体的路由。
  • 当具有相同 Order 和相同数量参数的路由与请求 URL 匹配时,会按添加到 PageConventionCollection 的顺序处理路由。

如果可能,请避免依赖于建立的路由处理顺序。通常,路由会通过 URL 匹配选择正确路由。如果必须设置路由 Order 属性以便正确路由请求,则应用的路由方案可能会使客户端感到困惑并且难以维护。应设法简化应用的路由方案。示例应用需要显式路由处理顺序以使用单个应用来演示几个路由方案。但是,在生产应用中应尝试避免设置路由 Order 的做法。

Razor Pages 路由和 MVC 控制器路由共享一个实现。有关 MVC 主题中的路由顺序的信息可在以下位置获得:路由到控制器操作:对属性路由排序

模型约定Model conventions

IPageConvention 添加委托,以添加应用于 Razor Pages 的模型约定

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

使用 Conventions 创建 IPageRouteModelConvention 并将其添加到 IPageConvention 实例集合中,这些实例将在页面路由模型构造过程中应用。

示例应用将 {globalTemplate?} 路由模板添加到应用中的所有页面:

  1. public class GlobalTemplatePageRouteModelConvention
  2. : IPageRouteModelConvention
  3. {
  4. public void Apply(PageRouteModel model)
  5. {
  6. var selectorCount = model.Selectors.Count;
  7. for (var i = 0; i < selectorCount; i++)
  8. {
  9. var selector = model.Selectors[i];
  10. model.Selectors.Add(new SelectorModel
  11. {
  12. AttributeRouteModel = new AttributeRouteModel
  13. {
  14. Order = 1,
  15. Template = AttributeRouteModel.CombineTemplates(
  16. selector.AttributeRouteModel.Template,
  17. "{globalTemplate?}"),
  18. }
  19. });
  20. }
  21. }
  22. }

AttributeRouteModelOrder 属性设置为 1这可确保在示例应用中实现以下路由匹配行为:

  • 本主题后面会添加 TheContactPage/{text?} 的路由模板。“联系人”页面路由具有默认顺序 null (Order = 0),因此它在 {globalTemplate?} 路由模板之前进行匹配。
  • 本主题后面会添加 {aboutTemplate?} 路由模板。为 {aboutTemplate?} 模板指定的 Order2。当在 /About/RouteDataValue 中请求“关于”页面时,由于设置了 Order 属性,“RouteDataValue”会加载到 RouteData.Values["globalTemplate"] (Order = 1) 而不是 RouteData.Values["aboutTemplate"] (Order = 2) 中。
  • 本主题后面会添加 {otherPagesTemplate?} 路由模板。为 {otherPagesTemplate?} 模板指定的 Order2。当使用路由参数请求 Pages/OtherPages 文件夹中的任何页面(例如,/OtherPages/Page1/RouteDataValue)时,由于设置了 Order 属性,因此“RouteDataValue”会加载到 RouteData.Values["globalTemplate"] (Order = 1) 中,而不是 RouteData.Values["otherPagesTemplate"] (Order = 2) 中。

尽可能不要将 Order 设置为 Order = 0依赖路由选择正确的路由。

将 MVC 添加到 Startup.ConfigureServices 中的服务集合时,会添加 Razor Pages 选项,例如添加 Conventions有关示例,请参阅示例应用

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

localhost:5000/About/GlobalRouteValue 中请求示例的“关于”页面并检查结果:

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

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

使用 Conventions 创建 IPageApplicationModelConvention 并将其添加到 IPageConvention 实例集合中,这些实例将在页面应用模型构造过程中应用。

为了演示此约定以及本主题后面的其他约定,示例应用包含了一个 AddHeaderAttribute 类。类构造函数采用 name 字符串和 values 字符串数组。将在其 OnResultExecuting 方法中使用这些值来设置响应标头。本主题后面的页面模型操作约定部分展示了完整的类。

示例应用使用 AddHeaderAttribute 类将标头 GlobalHeader 添加到应用中的所有页面:

  1. public class GlobalHeaderPageApplicationModelConvention
  2. : IPageApplicationModelConvention
  3. {
  4. public void Apply(PageApplicationModel model)
  5. {
  6. model.Filters.Add(new AddHeaderAttribute(
  7. "GlobalHeader", new string[] { "Global Header Value" }));
  8. }
  9. }

Startup.cs

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

localhost:5000/About 中请求示例的“关于”页面,并检查标头以查看结果:

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

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

使用 Conventions 创建 IPageHandlerModelConvention 并将其添加到 IPageConvention 实例集合中,这些实例将在页面处理程序模型构造过程中应用。

  1. public class GlobalPageHandlerModelConvention
  2. : IPageHandlerModelConvention
  3. {
  4. public void Apply(PageHandlerModel model)
  5. {
  6. // Access the PageHandlerModel
  7. }
  8. }

Startup.cs

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

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

默认路由模型提供程序派生自 IPageRouteModelProvider,可调用旨在为页面路由配置提供扩展点的约定。

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

使用 AddFolderRouteModelConvention 可创建和添加 IPageRouteModelConvention,它对于指定文件夹下的所有页面,会在 PageRouteModel 上调用操作。

示例应用使用 AddFolderRouteModelConvention{otherPagesTemplate?} 路由模板添加到 OtherPages 文件夹中的页面:

  1. options.Conventions.AddFolderRouteModelConvention("/OtherPages", model =>
  2. {
  3. var selectorCount = model.Selectors.Count;
  4. for (var i = 0; i < selectorCount; i++)
  5. {
  6. var selector = model.Selectors[i];
  7. model.Selectors.Add(new SelectorModel
  8. {
  9. AttributeRouteModel = new AttributeRouteModel
  10. {
  11. Order = 2,
  12. Template = AttributeRouteModel.CombineTemplates(
  13. selector.AttributeRouteModel.Template,
  14. "{otherPagesTemplate?}"),
  15. }
  16. });
  17. }
  18. });

AttributeRouteModelOrder 属性设置为 2这样可确保,当提供单个路由值时,优先将 {globalTemplate?} 的模板(已在本主题的前面部分设置为 1)作为第一个路由数据值位置。如果使用路由参数值请求 Pages/OtherPages 文件夹中的任何页面(例如,/OtherPages/Page1/RouteDataValue)时,由于设置了 Order 属性,因此“RouteDataValue”会加载到 RouteData.Values["globalTemplate"] (Order = 1) 中,而不是 RouteData.Values["otherPagesTemplate"] (Order = 2) 中。

尽可能不要将 Order 设置为 Order = 0依赖路由选择正确的路由。

localhost:5000/OtherPages/Page1/GlobalRouteValue/OtherPagesRouteValue 中请求示例的 Page1 页面并检查结果:

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

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

使用 AddPageRouteModelConvention 可创建和添加 IPageRouteModelConvention,它对于具有指定名称的页面,会在 PageRouteModel 上调用操作。

示例应用使用 AddPageRouteModelConvention{aboutTemplate?} 路由模板添加到“关于”页面:

  1. options.Conventions.AddPageRouteModelConvention("/About", model =>
  2. {
  3. var selectorCount = model.Selectors.Count;
  4. for (var i = 0; i < selectorCount; i++)
  5. {
  6. var selector = model.Selectors[i];
  7. model.Selectors.Add(new SelectorModel
  8. {
  9. AttributeRouteModel = new AttributeRouteModel
  10. {
  11. Order = 2,
  12. Template = AttributeRouteModel.CombineTemplates(
  13. selector.AttributeRouteModel.Template,
  14. "{aboutTemplate?}"),
  15. }
  16. });
  17. }
  18. });

AttributeRouteModelOrder 属性设置为 2这样可确保,当提供单个路由值时,优先将 {globalTemplate?} 的模板(已在本主题的前面部分设置为 1)作为第一个路由数据值位置。如果在 /About/RouteDataValue 中使用路由参数值请求“关于”页面,由于设置了 Order 属性,“RouteDataValue”会加载到 RouteData.Values["globalTemplate"] (Order = 1) 而不是 RouteData.Values["aboutTemplate"] (Order = 2) 中。

尽可能不要将 Order 设置为 Order = 0依赖路由选择正确的路由。

localhost:5000/About/GlobalRouteValue/AboutRouteValue 中请求示例的“关于”页面并检查结果:

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

配置页面路由Configure a page route

使用 AddPageRoute 配置路由,该路由指向指定页面路径中的页面。生成的页面链接使用指定的路由。AddPageRoute 使用 AddPageRouteModelConvention 建立路由。

示例应用为 Contact.cshtml 创建指向 /TheContactPage 的路由:

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

还可在 /Contact 中通过默认路由访问“联系人”页面。

示例应用的“联系人”页面自定义路由允许使用可选的 text 路由段 ({text?})。该页面还在其 @page 指令中包含此可选段,以便访问者在 /Contact 路由中访问该页面:

  1. @page "{text?}"
  2. @model ContactModel
  3. @{
  4. ViewData["Title"] = "Contact";
  5. }
  6. <h1>@ViewData["Title"]</h1>
  7. <h2>@Model.Message</h2>
  8. <address>
  9. One Microsoft Way<br>
  10. Redmond, WA 98052-6399<br>
  11. <abbr title="Phone">P:</abbr>
  12. 425.555.0100
  13. </address>
  14. <address>
  15. <strong>Support:</strong> <a href="mailto:Support@example.com">Support@example.com</a><br>
  16. <strong>Marketing:</strong> <a href="mailto:Marketing@example.com">Marketing@example.com</a>
  17. </address>
  18. <p>@Model.RouteDataTextTemplateValue</p>

请注意,在呈现的页面中,为联系人链接生成的 URL 反映了已更新的路由:

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

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

在常规路由 /Contact 或自定义路由 /TheContactPage 中访问“联系人”页面。如果提供附加的 text 路由段,该页面会显示所提供的 HTML 编码段:

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

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

实现 IPageApplicationModelProvider 的默认页面模型提供程序可调用约定,这些约定旨在为页面模型配置提供扩展点。在生成和修改页面发现及处理方案时,可使用这些约定。

对于此部分中的示例,示例应用使用 AddHeaderAttribute 类(一个 ResultFilterAttribute)来应用响应标头:

  1. public class AddHeaderAttribute : ResultFilterAttribute
  2. {
  3. private readonly string _name;
  4. private readonly string[] _values;
  5. public AddHeaderAttribute(string name, string[] values)
  6. {
  7. _name = name;
  8. _values = values;
  9. }
  10. public override void OnResultExecuting(ResultExecutingContext context)
  11. {
  12. context.HttpContext.Response.Headers.Add(_name, _values);
  13. base.OnResultExecuting(context);
  14. }
  15. }

示例演示了如何使用约定将该属性应用于某个文件夹中的所有页面以及单个页面。

文件夹应用模型约定

使用 AddFolderApplicationModelConvention 可创建和添加 IPageApplicationModelConvention,它对于指定文件夹下的所有页面,会在 PageApplicationModel 实例上调用操作。

示例演示了如何使用 AddFolderApplicationModelConvention 将标头 OtherPagesHeader 添加到应用的 OtherPages 文件夹内的页面:

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

localhost:5000/OtherPages/Page1 中请求示例的 Page1 页面,并检查标头以查看结果:

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

页面应用模型约定

使用 AddPageApplicationModelConvention 可创建和添加 IPageApplicationModelConvention,它对于具有指定名称的页面,会在 PageApplicationModel 上调用操作。

示例演示了如何使用 AddPageApplicationModelConvention 将标头 AboutHeader 添加到“关于”页面:

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

localhost:5000/About 中请求示例的“关于”页面,并检查标头以查看结果:

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

配置筛选器

ConfigureFilter 可配置要应用的指定筛选器。用户可以实现筛选器类,但示例应用演示了如何在 Lambda 表达式中实现筛选器,该筛选器在后台作为可返回筛选器的工厂实现:

  1. options.Conventions.ConfigureFilter(model =>
  2. {
  3. if (model.RelativePath.Contains("OtherPages/Page2"))
  4. {
  5. return new AddHeaderAttribute(
  6. "OtherPagesPage2Header",
  7. new string[] { "OtherPages/Page2 Header Value" });
  8. }
  9. return new EmptyFilter();
  10. });

页面应用模型用于检查指向 OtherPages 文件夹中 Page2 页面的段的相对路径。如果条件通过,则添加标头。如果不通过,则应用 EmptyFilter

EmptyFilter 是一种操作筛选器由于 Razor Pages 会忽略操作筛选器,因此,如果路径不包含 OtherPages/Page2EmptyFilter 会按预期没有影响。

localhost:5000/OtherPages/Page2 中请求示例的 Page2 页面,并检查标头以查看结果:

OtherPagesPage2Header 已添加到 Page2 的响应。

配置筛选器工厂

ConfigureFilter 可配置指定的工厂,以将筛选器应用于所有 Razor Pages。

示例应用提供了一个示例,说明如何使用筛选器工厂将具有两个值的标头 FilterFactoryHeader 添加到应用的页面:

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

AddHeaderWithFactory.cs

  1. public class AddHeaderWithFactory : IFilterFactory
  2. {
  3. // Implement IFilterFactory
  4. public IFilterMetadata CreateInstance(IServiceProvider serviceProvider)
  5. {
  6. return new AddHeaderFilter();
  7. }
  8. private class AddHeaderFilter : IResultFilter
  9. {
  10. public void OnResultExecuting(ResultExecutingContext context)
  11. {
  12. context.HttpContext.Response.Headers.Add(
  13. "FilterFactoryHeader",
  14. new string[]
  15. {
  16. "Filter Factory Header Value 1",
  17. "Filter Factory Header Value 2"
  18. });
  19. }
  20. public void OnResultExecuted(ResultExecutedContext context)
  21. {
  22. }
  23. }
  24. public bool IsReusable
  25. {
  26. get
  27. {
  28. return false;
  29. }
  30. }
  31. }

localhost:5000/About 中请求示例的“关于”页面,并检查标头以查看结果:

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

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

Razor 页面会忽略 MVC 操作筛选器,因为 Razor 页面使用处理程序方法。可以使用其他类型的 MVC 筛选器:授权异常资源结果有关详细信息,请参阅筛选器主题。

页面筛选器 (IPageFilter) 是应用于 Razor Pages 的一种筛选器。有关详细信息,请参阅 Razor 页面的筛选方法

其他资源Additional resources