- 模型约定Model conventions
- 页面路由操作约定Page route action conventions
- 配置页面路由Configure a page route
- MVC 筛选器和页面筛选器 (IPageFilter)MVC Filters and the Page filter (IPageFilter)
- 路由顺序Route order
- 使用参数转换程序自定义页面路由Use a parameter transformer to customize page routes
- 页面模型操作约定Page model action conventions
- 其他资源Additional resources
- 模型约定Model conventions
- 页面路由操作约定Page route action conventions
- 页面模型操作约定Page model action conventions
- 其他资源Additional resources
ASP.NET Core 中 Razor 页面的路由和应用约定Razor Pages route and app conventions in ASP.NET Core
需要为各个页面配置自定义页面路由时,可使用本主题稍后所述的 AddPageRoute 约定配置页面路由。
若要指定页面路由、添加路由段或向路由添加参数,请使用页面的 指令。有关详细信息,请参阅。
有些保留字不能用作路由段或参数名称。有关详细信息,请参阅路由:保留的路由名称。
(如何下载)
使用 扩展方法向 Startup
类中服务集合的 AddMvc 添加和配置 Razor Pages 约定。本主题稍后会介绍以下约定示例:
路由会为进行处理指定一个 (路由匹配)。
顺序 | 行为 |
---|---|
-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
为 添加委托,以添加应用于 Razor Pages 的模型约定。
将路由模型约定添加到所有页面Add a route model convention to all pages
使用 Conventions 创建 并将其添加到 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 属性设置为 1
。这可确保在示例应用中实现以下路由匹配行为:
- 本主题后面会添加
TheContactPage/{text?}
的路由模板。“联系人”页面路由具有默认顺序null
(Order = 0
),因此它在{globalTemplate?}
路由模板之前进行匹配。 - 本主题后面会添加
{aboutTemplate?}
路由模板。为{aboutTemplate?}
模板指定的Order
为2
。当在/About/RouteDataValue
中请求“关于”页面时,由于设置了Order
属性,“RouteDataValue”会加载到RouteData.Values["globalTemplate"]
(Order = 1
) 而不是RouteData.Values["aboutTemplate"]
(Order = 2
) 中。 - 本主题后面会添加
{otherPagesTemplate?}
路由模板。为{otherPagesTemplate?}
模板指定的Order
为2
。当使用路由参数请求 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 选项,例如添加 。有关示例,请参阅示例应用。
options.Conventions.Add(new GlobalTemplatePageRouteModelConvention());
在 localhost:5000/About/GlobalRouteValue
中请求示例的“关于”页面并检查结果:
将应用模型约定添加到所有页面Add an app model convention to all pages
使用 Conventions 创建 并将其添加到 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
中请求示例的“关于”页面,并检查标头以查看结果:
将处理程序模型约定添加到所有页面Add a handler model convention to all pages
使用 创建 IPageHandlerModelConvention 并将其添加到 实例集合中,这些实例将在页面处理程序模型构造过程中应用。
public class GlobalPageHandlerModelConvention
: IPageHandlerModelConvention
{
public void Apply(PageHandlerModel model)
{
// Access the PageHandlerModel
}
}
Startup.cs:
options.Conventions.Add(new GlobalPageHandlerModelConvention());
页面路由操作约定Page route action conventions
默认路由模型提供程序派生自 ,可调用旨在为页面路由配置提供扩展点的约定。
文件夹路由模型约定Folder route model convention
使用 可创建和添加 IPageRouteModelConvention,它对于指定文件夹下的所有页面,会在 上调用操作。
示例应用使用 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 属性设置为 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 页面并检查结果:
使用 可创建和添加 IPageRouteModelConvention,它对于具有指定名称的页面,会在 上调用操作。
示例应用使用 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?}"),
}
});
}
});
AttributeRouteModel 的 属性设置为 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
中请求示例的“关于”页面并检查结果:
使用参数转换程序自定义页面路由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
指令添加的路由段。该约定也不会转换 添加的路由。
PageRouteTransformerConvention
在 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();
}
}
配置页面路由Configure a page route
使用 配置路由,该路由指向指定页面路径中的页面。生成的页面链接使用指定的路由。AddPageRoute
使用 AddPageRouteModelConvention
建立路由。
示例应用为 Contact.cshtml 创建指向 /TheContactPage
的路由:
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 反映了已更新的路由:
在常规路由 /Contact
或自定义路由 /TheContactPage
中访问“联系人”页面。如果提供附加的 text
路由段,该页面会显示所提供的 HTML 编码段:
页面模型操作约定Page model action conventions
实现 的默认页面模型提供程序可调用约定,这些约定旨在为页面模型配置提供扩展点。在生成和修改页面发现及处理方案时,可使用这些约定。
对于此部分中的示例,示例应用使用 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);
}
}
示例演示了如何使用约定将该属性应用于某个文件夹中的所有页面以及单个页面。
文件夹应用模型约定
使用 可创建和添加 IPageApplicationModelConvention,它对于指定文件夹下的所有页面,会在 实例上调用操作。
示例演示了如何使用 AddFolderApplicationModelConvention
将标头 OtherPagesHeader
添加到应用的 OtherPages 文件夹内的页面:
options.Conventions.AddFolderApplicationModelConvention("/OtherPages", model =>
{
model.Filters.Add(new AddHeaderAttribute(
"OtherPagesHeader", new string[] { "OtherPages Header Value" }));
});
在 localhost:5000/OtherPages/Page1
中请求示例的 Page1 页面,并检查标头以查看结果:
页面应用模型约定
使用 AddPageApplicationModelConvention 可创建和添加 ,它对于具有指定名称的页面,会在 PageApplicationModel 上调用操作。
示例演示了如何使用 AddPageApplicationModelConvention
将标头 AboutHeader
添加到“关于”页面:
options.Conventions.AddPageApplicationModelConvention("/About", model =>
{
model.Filters.Add(new AddHeaderAttribute(
"AboutHeader", new string[] { "About Header Value" }));
});
在 localhost:5000/About
中请求示例的“关于”页面,并检查标头以查看结果:
配置筛选器
可配置要应用的指定筛选器。用户可以实现筛选器类,但示例应用演示了如何在 Lambda 表达式中实现筛选器,该筛选器在后台作为可返回筛选器的工厂实现:
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 页面的段的相对路径。如果条件通过,则添加标头。如果不通过,则应用 EmptyFilter
。
EmptyFilter
是一种操作筛选器。由于 Razor Pages 会忽略操作筛选器,因此,如果路径不包含 OtherPages/Page2
,EmptyFilter
会按预期没有影响。
在 localhost:5000/OtherPages/Page2
中请求示例的 Page2 页面,并检查标头以查看结果:
配置筛选器工厂
可配置指定的工厂,以将筛选器应用于所有 Razor Pages。
示例应用提供了一个示例,说明如何使用将具有两个值的标头 FilterFactoryHeader
添加到应用的页面:
options.Conventions.ConfigureFilter(new AddHeaderWithFactory());
AddHeaderWithFactory.cs:
在 localhost:5000/About
中请求示例的“关于”页面,并检查标头以查看结果:
MVC 筛选器和页面筛选器 (IPageFilter)MVC Filters and the Page filter (IPageFilter)
页面筛选器 () 是应用于 Razor Pages 的一种筛选器。有关详细信息,请参阅 Razor 页面的筛选方法。
了解如何使用来控制 Razor 页面应用中的页面路由、发现和处理。
需要为各个页面配置自定义页面路由时,可使用本主题稍后所述的 AddPageRoute 约定配置页面路由。
若要指定页面路由、添加路由段或向路由添加参数,请使用页面的 @page
指令。有关详细信息,请参阅。
有些保留字不能用作路由段或参数名称。有关详细信息,请参阅路由:保留的路由名称。
(如何下载)
使用 扩展方法向 Startup
类中服务集合的 AddMvc 添加和配置 Razor Pages 约定。本主题稍后会介绍以下约定示例:
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(路由匹配)。
顺序 | 行为 |
---|---|
-1 | 在处理其他路由之前处理该路由。 |
0 | 未指定顺序(默认值)。不分配 Order (Order = null ) 会将路由 默认为 0(零)以进行处理。 |
1、2 … n | 指定路由处理顺序。 |
按约定建立路由处理:
- 按顺序处理路由(-1、0、1、2 … n)。
- 当路由具有相同
Order
时,首先匹配最具体的路由,然后匹配不太具体的路由。 - 当具有相同
Order
和相同数量参数的路由与请求 URL 匹配时,会按添加到 的顺序处理路由。
如果可能,请避免依赖于建立的路由处理顺序。通常,路由会通过 URL 匹配选择正确路由。如果必须设置路由 Order
属性以便正确路由请求,则应用的路由方案可能会使客户端感到困惑并且难以维护。应设法简化应用的路由方案。示例应用需要显式路由处理顺序以使用单个应用来演示几个路由方案。但是,在生产应用中应尝试避免设置路由 Order
的做法。
Razor Pages 路由和 MVC 控制器路由共享一个实现。有关 MVC 主题中的路由顺序的信息可在以下位置获得:路由到控制器操作:对属性路由排序。
模型约定Model conventions
为 IPageConvention 添加委托,以添加应用于 Razor Pages 的。
将路由模型约定添加到所有页面Add a route model convention to all pages
使用 创建 IPageRouteModelConvention 并将其添加到 实例集合中,这些实例将在页面路由模型构造过程中应用。
示例应用将 {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?}"),
}
});
}
}
}
AttributeRouteModel 的 属性设置为 1
。这可确保在示例应用中实现以下路由匹配行为:
- 本主题后面会添加
TheContactPage/{text?}
的路由模板。“联系人”页面路由具有默认顺序null
(Order = 0
),因此它在{globalTemplate?}
路由模板之前进行匹配。 - 本主题后面会添加
{aboutTemplate?}
路由模板。为{aboutTemplate?}
模板指定的Order
为2
。当在/About/RouteDataValue
中请求“关于”页面时,由于设置了Order
属性,“RouteDataValue”会加载到RouteData.Values["globalTemplate"]
(Order = 1
) 而不是RouteData.Values["aboutTemplate"]
(Order = 2
) 中。 - 本主题后面会添加
{otherPagesTemplate?}
路由模板。为{otherPagesTemplate?}
模板指定的Order
为2
。当使用路由参数请求 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。有关示例,请参阅。
options.Conventions.Add(new GlobalTemplatePageRouteModelConvention());
在 localhost:5000/About/GlobalRouteValue
中请求示例的“关于”页面并检查结果:
将应用模型约定添加到所有页面Add an app model convention to all pages
使用 创建 IPageApplicationModelConvention 并将其添加到 实例集合中,这些实例将在页面应用模型构造过程中应用。
为了演示此约定以及本主题后面的其他约定,示例应用包含了一个 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
中请求示例的“关于”页面,并检查标头以查看结果:
将处理程序模型约定添加到所有页面Add a handler model convention to all pages
使用 Conventions 创建 并将其添加到 IPageConvention 实例集合中,这些实例将在页面处理程序模型构造过程中应用。
public class GlobalPageHandlerModelConvention
: IPageHandlerModelConvention
{
public void Apply(PageHandlerModel model)
{
// Access the PageHandlerModel
}
}
Startup.cs:
options.Conventions.Add(new GlobalPageHandlerModelConvention());
页面路由操作约定Page route action conventions
默认路由模型提供程序派生自 IPageRouteModelProvider,可调用旨在为页面路由配置提供扩展点的约定。
文件夹路由模型约定Folder route model convention
使用 AddFolderRouteModelConvention 可创建和添加 ,它对于指定文件夹下的所有页面,会在 PageRouteModel 上调用操作。
示例应用使用 将 {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?}"),
}
});
}
});
AttributeRouteModel 的 属性设置为 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 页面并检查结果:
使用 AddPageRouteModelConvention 可创建和添加 ,它对于具有指定名称的页面,会在 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 属性设置为 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
中请求示例的“关于”页面并检查结果:
使用参数转换程序自定义页面路由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 添加的路由。
PageRouteTransformerConvention
在 Startup.ConfigureServices
中注册为选项:
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 配置路由,该路由指向指定页面路径中的页面。生成的页面链接使用指定的路由。AddPageRoute
使用 AddPageRouteModelConvention
建立路由。
示例应用为 Contact.cshtml 创建指向 /TheContactPage
的路由:
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 反映了已更新的路由:
在常规路由 /Contact
或自定义路由 /TheContactPage
中访问“联系人”页面。如果提供附加的 text
路由段,该页面会显示所提供的 HTML 编码段:
页面模型操作约定Page model action conventions
实现 IPageApplicationModelProvider 的默认页面模型提供程序可调用约定,这些约定旨在为页面模型配置提供扩展点。在生成和修改页面发现及处理方案时,可使用这些约定。
对于此部分中的示例,示例应用使用 AddHeaderAttribute
类(一个 )来应用响应标头:
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 可创建和添加 ,它对于指定文件夹下的所有页面,会在 PageApplicationModel 实例上调用操作。
示例演示了如何使用 AddFolderApplicationModelConvention
将标头 OtherPagesHeader
添加到应用的 OtherPages 文件夹内的页面:
options.Conventions.AddFolderApplicationModelConvention("/OtherPages", model =>
{
model.Filters.Add(new AddHeaderAttribute(
"OtherPagesHeader", new string[] { "OtherPages Header Value" }));
});
在 localhost:5000/OtherPages/Page1
中请求示例的 Page1 页面,并检查标头以查看结果:
页面应用模型约定
使用 可创建和添加 IPageApplicationModelConvention,它对于具有指定名称的页面,会在 上调用操作。
示例演示了如何使用 AddPageApplicationModelConvention
将标头 AboutHeader
添加到“关于”页面:
options.Conventions.AddPageApplicationModelConvention("/About", model =>
{
model.Filters.Add(new AddHeaderAttribute(
"AboutHeader", new string[] { "About Header Value" }));
});
在 localhost:5000/About
中请求示例的“关于”页面,并检查标头以查看结果:
配置筛选器
ConfigureFilter 可配置要应用的指定筛选器。用户可以实现筛选器类,但示例应用演示了如何在 Lambda 表达式中实现筛选器,该筛选器在后台作为可返回筛选器的工厂实现:
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 页面的段的相对路径。如果条件通过,则添加标头。如果不通过,则应用 EmptyFilter
。
EmptyFilter
是一种。由于 Razor Pages 会忽略操作筛选器,因此,如果路径不包含 OtherPages/Page2
,EmptyFilter
会按预期没有影响。
在 localhost:5000/OtherPages/Page2
中请求示例的 Page2 页面,并检查标头以查看结果:
配置筛选器工厂
ConfigureFilter 可配置指定的工厂,以将应用于所有 Razor Pages。
示例应用提供了一个示例,说明如何使用筛选器工厂将具有两个值的标头 FilterFactoryHeader
添加到应用的页面:
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
{
}
}
}
Razor 页面会忽略 MVC ,因为 Razor 页面使用处理程序方法。可以使用其他类型的 MVC 筛选器:授权、、资源和。有关详细信息,请参阅筛选器主题。
页面筛选器 () 是应用于 Razor Pages 的一种筛选器。有关详细信息,请参阅 Razor 页面的筛选方法。
其他资源Additional resources
了解如何使用页面路由和应用模型提供程序约定来控制 Razor 页面应用中的页面路由、发现和处理。
需要为各个页面配置自定义页面路由时,可使用本主题稍后所述的 配置页面路由。
若要指定页面路由、添加路由段或向路由添加参数,请使用页面的 @page
指令。有关详细信息,请参阅自定义路由。
有些保留字不能用作路由段或参数名称。有关详细信息,请参阅。
使用 AddRazorPagesOptions 扩展方法向 Startup
类中服务集合的 添加和配置 Razor Pages 约定。本主题稍后会介绍以下约定示例:
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
路由会为进行处理指定一个 (路由匹配)。
顺序 | 行为 |
---|---|
-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
为 添加委托,以添加应用于 Razor Pages 的模型约定。
将路由模型约定添加到所有页面Add a route model convention to all pages
使用 Conventions 创建 并将其添加到 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 属性设置为 1
。这可确保在示例应用中实现以下路由匹配行为:
- 本主题后面会添加
TheContactPage/{text?}
的路由模板。“联系人”页面路由具有默认顺序null
(Order = 0
),因此它在{globalTemplate?}
路由模板之前进行匹配。 - 本主题后面会添加
{aboutTemplate?}
路由模板。为{aboutTemplate?}
模板指定的Order
为2
。当在/About/RouteDataValue
中请求“关于”页面时,由于设置了Order
属性,“RouteDataValue”会加载到RouteData.Values["globalTemplate"]
(Order = 1
) 而不是RouteData.Values["aboutTemplate"]
(Order = 2
) 中。 - 本主题后面会添加
{otherPagesTemplate?}
路由模板。为{otherPagesTemplate?}
模板指定的Order
为2
。当使用路由参数请求 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 选项,例如添加 。有关示例,请参阅示例应用。
options.Conventions.Add(new GlobalTemplatePageRouteModelConvention());
在 localhost:5000/About/GlobalRouteValue
中请求示例的“关于”页面并检查结果:
将应用模型约定添加到所有页面Add an app model convention to all pages
使用 Conventions 创建 并将其添加到 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
中请求示例的“关于”页面,并检查标头以查看结果:
将处理程序模型约定添加到所有页面Add a handler model convention to all pages
使用 创建 IPageHandlerModelConvention 并将其添加到 实例集合中,这些实例将在页面处理程序模型构造过程中应用。
public class GlobalPageHandlerModelConvention
: IPageHandlerModelConvention
{
public void Apply(PageHandlerModel model)
{
// Access the PageHandlerModel
}
}
Startup.cs:
options.Conventions.Add(new GlobalPageHandlerModelConvention());
页面路由操作约定Page route action conventions
默认路由模型提供程序派生自 ,可调用旨在为页面路由配置提供扩展点的约定。
文件夹路由模型约定Folder route model convention
使用 可创建和添加 IPageRouteModelConvention,它对于指定文件夹下的所有页面,会在 上调用操作。
示例应用使用 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 属性设置为 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 页面并检查结果:
使用 可创建和添加 IPageRouteModelConvention,它对于具有指定名称的页面,会在 上调用操作。
示例应用使用 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?}"),
}
});
}
});
AttributeRouteModel 的 属性设置为 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
中请求示例的“关于”页面并检查结果:
配置页面路由Configure a page route
使用 配置路由,该路由指向指定页面路径中的页面。生成的页面链接使用指定的路由。AddPageRoute
使用 AddPageRouteModelConvention
建立路由。
示例应用为 Contact.cshtml 创建指向 /TheContactPage
的路由:
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 反映了已更新的路由:
在常规路由 /Contact
或自定义路由 /TheContactPage
中访问“联系人”页面。如果提供附加的 text
路由段,该页面会显示所提供的 HTML 编码段:
页面模型操作约定Page model action conventions
实现 的默认页面模型提供程序可调用约定,这些约定旨在为页面模型配置提供扩展点。在生成和修改页面发现及处理方案时,可使用这些约定。
对于此部分中的示例,示例应用使用 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);
}
}
示例演示了如何使用约定将该属性应用于某个文件夹中的所有页面以及单个页面。
文件夹应用模型约定
使用 可创建和添加 IPageApplicationModelConvention,它对于指定文件夹下的所有页面,会在 实例上调用操作。
示例演示了如何使用 AddFolderApplicationModelConvention
将标头 OtherPagesHeader
添加到应用的 OtherPages 文件夹内的页面:
options.Conventions.AddFolderApplicationModelConvention("/OtherPages", model =>
{
model.Filters.Add(new AddHeaderAttribute(
"OtherPagesHeader", new string[] { "OtherPages Header Value" }));
});
在 localhost:5000/OtherPages/Page1
中请求示例的 Page1 页面,并检查标头以查看结果:
页面应用模型约定
使用 AddPageApplicationModelConvention 可创建和添加 ,它对于具有指定名称的页面,会在 PageApplicationModel 上调用操作。
示例演示了如何使用 AddPageApplicationModelConvention
将标头 AboutHeader
添加到“关于”页面:
options.Conventions.AddPageApplicationModelConvention("/About", model =>
{
model.Filters.Add(new AddHeaderAttribute(
"AboutHeader", new string[] { "About Header Value" }));
});
在 localhost:5000/About
中请求示例的“关于”页面,并检查标头以查看结果:
配置筛选器
可配置要应用的指定筛选器。用户可以实现筛选器类,但示例应用演示了如何在 Lambda 表达式中实现筛选器,该筛选器在后台作为可返回筛选器的工厂实现:
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 页面的段的相对路径。如果条件通过,则添加标头。如果不通过,则应用 EmptyFilter
。
EmptyFilter
是一种操作筛选器。由于 Razor Pages 会忽略操作筛选器,因此,如果路径不包含 OtherPages/Page2
,EmptyFilter
会按预期没有影响。
在 localhost:5000/OtherPages/Page2
中请求示例的 Page2 页面,并检查标头以查看结果:
配置筛选器工厂
可配置指定的工厂,以将筛选器应用于所有 Razor Pages。
示例应用提供了一个示例,说明如何使用将具有两个值的标头 FilterFactoryHeader
添加到应用的页面:
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
中请求示例的“关于”页面,并检查标头以查看结果:
页面筛选器 (IPageFilter) 是应用于 Razor Pages 的一种筛选器。有关详细信息,请参阅 。