ASP.NET Core 中的 Razor Pages 路由和應用程式慣例
了解如何使用頁面路由和應用程式模型提供者慣例,來控制 Razor Pages 應用程式中的頁面路由、探索與處理。
若要指定頁面路由、新增路由區段或將參數新增至路由,請使用頁面的 @page
指示詞。 如需詳細資訊,請參閱自訂路由。
有無法做為路由區段或參數名稱的保留字。 如需詳細資訊,請參閱路由:保留路由名稱。
檢視或下載範例程式碼 \(英文\) (如何下載)
案例 | 範例會示範 |
---|---|
模型慣例 Conventions.Add |
將路由範本和標頭新增至應用程式的頁面。 |
頁面路由動作慣例 | 將路由範本新增至資料夾中的頁面,以及新增至單一頁面。 |
頁面模型動作慣例
|
將標頭新增至資料夾中的頁面、將標頭新增至單一頁面,以及設定篩選條件 Factory 將標頭新增至應用程式的頁面。 |
Razor Pages 慣例是使用設定 RazorPagesOptions 的 AddRazorPages 多載來設定。 稍後在本主題會說明下列慣例範例:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages(options =>
{
options.Conventions.Add( ... );
options.Conventions.AddFolderRouteModelConvention(
"/OtherPages", model => { ... });
options.Conventions.AddPageRouteModelConvention(
"/About", model => { ... });
options.Conventions.AddPageRoute(
"/Contact", "TheContactPage/{text?}");
options.Conventions.AddFolderApplicationModelConvention(
"/OtherPages", model => { ... });
options.Conventions.AddPageApplicationModelConvention(
"/About", model => { ... });
options.Conventions.ConfigureFilter(model => { ... });
options.Conventions.ConfigureFilter( ... );
});
}
路由順序
路由會為處理指定 Order (比對路由)。
路由順序 | 行為 |
---|---|
-1 | 在處理其他路由之前,會先處理此路由。 |
0 | 未指定順序 (預設值)。 未指派 Order (Order = null ) 會將路由 Order 預設為 0 (零) 進行處理。 |
1, 2, … n | 指定路由處理順序。 |
路由處理是由慣例所建立:
- 路由會循序處理 (-1、0、1、2... n)。
- 路由具有相同
Order
時,會先比對最特定的路由,接著再比對較不特定的路由。 - 在具有相同
Order
和相同數目參數的路由符合要求 URL 時,路由會依新增至 PageConventionCollection 的順序進行處理。
如果可能,請避免依賴已建立的路由處理順序。 一般而言,路由會選取具有 URL 比對的正確路由。 如果您必須設定路由 Order
屬性才能正確地傳送路由要求,則應用程式的路由配置可能會造成用戶端混淆,而且難以維護。 尋求簡化應用程式的路由配置。 範例應用程式需要明確的路由處理順序,才能使用單一應用程式來示範數個路由案例。 不過,您應該嘗試避免在生產應用程式中設定路由 Order
的做法。
Razor Pages 路由和 MVC 控制器路由會共用實作。 MVC 主題中有關路由順序的資訊,可在路由傳送至控制器動作:排序屬性路由中取得。
模型慣例
新增 IPageConvention 的委派,以新增會套用至 Razor Pages 的模型慣例。
將路由模型慣例新增至所有頁面
使用 Conventions 來建立和新增 IPageRouteModelConvention 至頁面路由模型建構期間所套用的 IPageConvention 執行個體集合。
範例應用程式包含 GlobalTemplatePageRouteModelConvention
類別,以將 {globalTemplate?}
路由範本新增至應用程式中的所有頁面:
using Microsoft.AspNetCore.Mvc.ApplicationModels;
namespace SampleApp.Conventions;
public class GlobalTemplatePageRouteModelConvention : IPageRouteModelConvention
{
public void Apply(PageRouteModel model)
{
var selectorCount = model.Selectors.Count;
for (var i = 0; i < selectorCount; i++)
{
var selector = model.Selectors[i];
model.Selectors.Add(new SelectorModel
{
AttributeRouteModel = new AttributeRouteModel
{
Order = 1,
Template = AttributeRouteModel.CombineTemplates(
selector.AttributeRouteModel!.Template,
"{globalTemplate?}"),
}
});
}
}
}
在上述程式碼中:
- PageRouteModel 會傳遞至 Apply 方法。
- PageRouteModel.Selectors 會取得選取器計數。
- 已新增 SelectorModel,其中包含 AttributeRouteModel
將 Razor Pages 新增至服務集合後,系統會新增 Razor Pages 選項 (例如新增 Conventions)。 如需範例,請參閱範例應用程式。
using Microsoft.AspNetCore.Mvc.ApplicationModels;
using Microsoft.EntityFrameworkCore;
using SampleApp.Conventions;
using SampleApp.Data;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<AppDbContext>(options =>
options.UseInMemoryDatabase("InMemoryDb"));
builder.Services.AddRazorPages(options =>
{
options.Conventions.Add(new GlobalTemplatePageRouteModelConvention());
options.Conventions.AddFolderRouteModelConvention("/OtherPages", model =>
{
var selectorCount = model.Selectors.Count;
for (var i = 0; i < selectorCount; i++)
{
var selector = model.Selectors[i];
model.Selectors.Add(new SelectorModel
{
AttributeRouteModel = new AttributeRouteModel
{
Order = 2,
Template = AttributeRouteModel.CombineTemplates(
selector.AttributeRouteModel!.Template,
"{otherPagesTemplate?}"),
}
});
}
});
options.Conventions.AddPageRouteModelConvention("/About", model =>
{
var selectorCount = model.Selectors.Count;
for (var i = 0; i < selectorCount; i++)
{
var selector = model.Selectors[i];
model.Selectors.Add(new SelectorModel
{
AttributeRouteModel = new AttributeRouteModel
{
Order = 2,
Template = AttributeRouteModel.CombineTemplates(
selector.AttributeRouteModel!.Template,
"{aboutTemplate?}"),
}
});
}
});
});
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseAuthorization();
app.MapRazorPages();
app.Run();
請考慮 GlobalTemplatePageRouteModelConvention
類別:
using Microsoft.AspNetCore.Mvc.ApplicationModels;
namespace SampleApp.Conventions;
public class GlobalTemplatePageRouteModelConvention : IPageRouteModelConvention
{
public void Apply(PageRouteModel model)
{
var selectorCount = model.Selectors.Count;
for (var i = 0; i < selectorCount; i++)
{
var selector = model.Selectors[i];
model.Selectors.Add(new SelectorModel
{
AttributeRouteModel = new AttributeRouteModel
{
Order = 1,
Template = AttributeRouteModel.CombineTemplates(
selector.AttributeRouteModel!.Template,
"{globalTemplate?}"),
}
});
}
}
}
AttributeRouteModel 的 Order 屬性設定為 1
。 這可確保範例應用程式中的下列路由比對行為:
本主題稍後會新增
TheContactPage/{text?}
的路由範本。Contact Page
路由的預設順序為null
(Order = 0
),因此它在具有Order = 1
的{globalTemplate?}
路由範本之前比對。{aboutTemplate?}
路由範本會顯示在上述程式碼中。{aboutTemplate?}
範本會指定Order
為2
。 在/About/RouteDataValue
上要求 About 頁面時,由於設定Order
屬性之故,因此 "RouteDataValue" 會載入至RouteData.Values["globalTemplate"]
(Order = 1
),而不是RouteData.Values["aboutTemplate"]
(Order = 2
)。{otherPagesTemplate?}
路由範本會顯示在上述程式碼中。{otherPagesTemplate?}
範本會指定Order
為2
。 若路由參數要求 Pages/OtherPages 資料夾中的任何頁面:例如,
/OtherPages/Page1/xyz
路由資料值
"xyz"
會載入RouteData.Values["globalTemplate"]
(Order = 1
)。由於
Order
屬性2
具有較高的值,因此未載入具有 (Order = 2
) 的RouteData.Values["otherPagesTemplate"]
。
可能的話,請勿設定 Order
。 如果未設定 Order
,則預設為 Order = 0
。 依賴路由而不是 Order
屬性來選取正確的路由。
在 localhost:{port}/About/GlobalRouteValue
上要求範例的 About
頁面,並檢查結果:
範例應用程式會使用 Rick.Docs.Samples.RouteInfo NuGet 套件,在記錄輸出中顯示路由資訊。 使用 localhost:{port}/About/GlobalRouteValue
,記錄器會顯示所使用的要求、Order
和範本:
info: SampleApp.Pages.AboutModel[0]
/About/GlobalRouteValue Order = 1 Template = About/{globalTemplate?}
將應用程式模型慣例新增至所有頁面
使用 Conventions 來建立和新增 IPageApplicationModelConvention 至頁面應用程式模型建構期間所套用的 IPageConvention 執行個體集合。
為了示範這個慣例和本主題稍後的其他慣例,範例應用程式包含了 AddHeaderAttribute
類別。 類別建構函式接受 name
字串和 values
字串陣列。 在其 OnResultExecuting
方法中使用這些值來設定回應標頭。 完整的類別顯示在本主題稍後的頁面模型動作慣例一節中。
範例應用程式會使用 AddHeaderAttribute
類別,將標頭 GlobalHeader
新增至應用程式中的所有頁面:
public class GlobalHeaderPageApplicationModelConvention
: IPageApplicationModelConvention
{
public void Apply(PageApplicationModel model)
{
model.Filters.Add(new AddHeaderAttribute(
"GlobalHeader", new string[] { "Global Header Value" }));
}
}
Program.cs
:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<AppDbContext>(options =>
options.UseInMemoryDatabase("InMemoryDb"));
builder.Services.AddRazorPages(options =>
{
options.Conventions.Add(new GlobalTemplatePageRouteModelConvention());
options.Conventions.Add(new GlobalHeaderPageApplicationModelConvention());
在 localhost:{port}/About
上要求範例的 About 頁面,並檢查標頭來檢視結果:
將處理常式模型慣例新增至所有頁面
使用 Conventions 來建立並新增 IPageHandlerModelConvention 至頁面處理常式模型建構期間所套用的 IPageConvention 執行個體集合。
public class GlobalPageHandlerModelConvention
: IPageHandlerModelConvention
{
public void Apply(PageHandlerModel model)
{
// Access the PageHandlerModel
}
}
頁面路由動作慣例
衍生自 IPageRouteModelProvider 的預設路由模型提供者會叫用慣例,這些慣例是為了要提供設定頁面路由的擴充點。
資料夾路由模型慣例
使用 AddFolderRouteModelConvention 來建立和新增 IPageRouteModelConvention,針對指定資料夾底下的所有頁面在 PageRouteModel 上叫用動作。
範例應用程式會使用 AddFolderRouteModelConvention,將 {otherPagesTemplate?}
路由範本新增至 OtherPages 資料夾中的頁面:
options.Conventions.AddFolderRouteModelConvention("/OtherPages", model =>
{
var selectorCount = model.Selectors.Count;
for (var i = 0; i < selectorCount; i++)
{
var selector = model.Selectors[i];
model.Selectors.Add(new SelectorModel
{
AttributeRouteModel = new AttributeRouteModel
{
Order = 2,
Template = AttributeRouteModel.CombineTemplates(
selector.AttributeRouteModel!.Template,
"{otherPagesTemplate?}"),
}
});
}
});
AttributeRouteModel 的 Order 屬性設定為 2
。 這可確保在提供單一路由值時,{globalTemplate?}
的範本 (稍早在本主題中設定為 1
) 會指定第一個路由資料值位置的優先順序。 如果使用路由參數值 (例如 /OtherPages/Page1/RouteDataValue
) 要求 Pages/OtherPages 資料夾中的某個頁面,則由於已設定 Order
屬性,系統會將 "RouteDataValue" 載入到 RouteData.Values["globalTemplate"]
(Order = 1
),而不是 RouteData.Values["otherPagesTemplate"]
(Order = 2
)。
盡可能不要設定 Order
,這會導致 Order = 0
。 依賴路由來選取正確的路由。
在 localhost:5000/OtherPages/Page1/GlobalRouteValue/OtherPagesRouteValue
上要求範例的 Page1 頁面,並檢查結果:
頁面路由模型慣例
使用 AddPageRouteModelConvention 來建立和新增 IPageRouteModelConvention,針對具有指定名稱的頁面在 PageRouteModel 上叫用動作。
範例應用程式會使用 AddPageRouteModelConvention
,將 {aboutTemplate?}
路由範本新增至 About 頁面:
options.Conventions.AddPageRouteModelConvention("/About", model =>
{
var selectorCount = model.Selectors.Count;
for (var i = 0; i < selectorCount; i++)
{
var selector = model.Selectors[i];
model.Selectors.Add(new SelectorModel
{
AttributeRouteModel = new AttributeRouteModel
{
Order = 2,
Template = AttributeRouteModel.CombineTemplates(
selector.AttributeRouteModel!.Template,
"{aboutTemplate?}"),
}
});
}
});
AttributeRouteModel 的 Order 屬性設定為 2
。 這可確保在提供單一路由值時,{globalTemplate?}
的範本 (稍早在本主題中設定為 1
) 會指定第一個路由資料值位置的優先順序。 如果使用 /About/RouteDataValue
上的路由參數值要求 [關於] 頁面,則由於 Order
屬性已設定,系統會將 "RouteDataValue" 載入 RouteData.Values["globalTemplate"]
(Order = 1
) 而非 RouteData.Values["aboutTemplate"]
(Order = 2
)。
盡可能不要設定 Order
,這會導致 Order = 0
。 依賴路由來選取正確的路由。
在 localhost:{port}/About/GlobalRouteValue/AboutRouteValue
上要求範例的 About 頁面,並檢查結果:
記錄器輸出會顯示:
info: SampleApp.Pages.AboutModel[0]
/About/GlobalRouteValue/AboutRouteValue Order = 2 Template = About/{globalTemplate?}/{aboutTemplate?}
使用參數轉換器自訂頁面路由
請參閱參數轉換器。
設定頁面路由
使用 AddPageRoute 以設定路由至指定頁面路徑上的頁面。 產生至此頁面的連結會使用指定的路由。 AddPageRoute 使用 AddPageRouteModelConvention 來建立路由。
範例應用程式會為 Contact
Razor 頁面建立通往 /TheContactPage
的路由:
options.Conventions.AddPageRoute("/Contact", "TheContactPage/{text?}");
您也可以透過預設路由,在 [/
Contact1] 連線到 Contact
頁面。
範例應用程式的 Contact
頁面自訂路由允許使用選擇性的 text
路由區段 ({text?}
)。 該頁面也會在其 @page
指示詞中包含這個選擇性區段,以防訪客在其 /Contact
路由上存取頁面:
@page "{text?}"
@model ContactModel
@{
ViewData["Title"] = "Contact";
}
<h1>@ViewData["Title"]</h1>
<h2>@Model.Message</h2>
<address>
One Microsoft Way<br>
Redmond, WA 98052-6399<br>
<abbr title="Phone">P:</abbr>
425.555.0100
</address>
<address>
<strong>Support:</strong> <a href="mailto:Support@example.com">Support@example.com</a><br>
<strong>Marketing:</strong> <a href="mailto:Marketing@example.com">Marketing@example.com</a>
</address>
<p>@Model.RouteDataTextTemplateValue</p>
請注意,呈現頁面中針對 Contact 連結所產生的 URL 會反映更新的路由:
請在其一般路由 /Contact
或自訂路由 /TheContactPage
上瀏覽 Contact
頁面。 如果您提供額外的 text
路由區段,該頁面會顯示您提供的 HTML 編碼區段:
頁面模型動作慣例
實作 IPageApplicationModelProvider 的預設頁面模型提供者會叫用慣例,這些慣例是為了要提供設定頁面模型的擴充點。 在建置和修改頁面探索與處理案例時,這些慣例很有用。
對於本節中的範例,範例應用程式會使用 AddHeaderAttribute
類別,這是可套用回應標頭的 ResultFilterAttribute:
public class AddHeaderAttribute : ResultFilterAttribute
{
private readonly string _name;
private readonly string[] _values;
public AddHeaderAttribute(string name, string[] values)
{
_name = name;
_values = values;
}
public override void OnResultExecuting(ResultExecutingContext context)
{
context.HttpContext.Response.Headers.Add(_name, _values);
base.OnResultExecuting(context);
}
}
透過慣例,此範例示範如何將屬性套用至資料夾中的所有頁面,以及套用至單一頁面。
資料夾應用程式模型慣例
使用 AddFolderApplicationModelConvention 來建立和新增 IPageApplicationModelConvention,在指定資料夾底下所有頁面的 PageApplicationModel 執行個體上叫用動作。
此範例示範如何將標頭 OtherPagesHeader
新增至應用程式的 OtherPages 資料夾內的頁面來使用 AddFolderApplicationModelConvention
:
options.Conventions.AddFolderApplicationModelConvention("/OtherPages", model =>
{
model.Filters.Add(new AddHeaderAttribute(
"OtherPagesHeader", new string[] { "OtherPages Header Value" }));
});
在 localhost:5000/OtherPages/Page1
上要求範例的 Page1 頁面,並檢查標頭來檢視結果:
頁面應用程式模型慣例
使用 AddPageApplicationModelConvention 來建立和新增 IPageApplicationModelConvention,針對具有指定名稱的頁面在 PageApplicationModel 上叫用動作。
此範例示範如何將標頭 AboutHeader
新增至 About 頁面來使用 AddPageApplicationModelConvention
:
options.Conventions.AddPageApplicationModelConvention("/About", model =>
{
model.Filters.Add(new AddHeaderAttribute(
"AboutHeader", new string[] { "About Header Value" }));
});
在 localhost:5000/About
上要求範例的 About 頁面,並檢查標頭來檢視結果:
設定篩選條件
ConfigureFilter 會設定要套用的指定篩選條件。 您可以實作篩選條件類別,但範例應用程式是示範如何在 Lambda 運算式中實作篩選條件,該運算式會在幕後實作為 Factory 以傳回篩選條件:
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 頁面,並檢查標頭來檢視結果:
設定篩選條件 Factory
ConfigureFilter 會設定指定的 Factory,以將篩選條件套用至所有 Razor 頁面。
範例應用程式示範如何以應用程式頁面的兩個值新增標頭 FilterFactoryHeader
來使用篩選條件 Factory:
options.Conventions.ConfigureFilter(new AddHeaderWithFactory());
AddHeaderWithFactory.cs
:
public class AddHeaderWithFactory : IFilterFactory
{
// Implement IFilterFactory
public IFilterMetadata CreateInstance(IServiceProvider serviceProvider)
{
return new AddHeaderFilter();
}
private class AddHeaderFilter : IResultFilter
{
public void OnResultExecuting(ResultExecutingContext context)
{
context.HttpContext.Response.Headers.Add(
"FilterFactoryHeader",
new string[]
{
"Filter Factory Header Value 1",
"Filter Factory Header Value 2"
});
}
public void OnResultExecuted(ResultExecutedContext context)
{
}
}
public bool IsReusable
{
get
{
return false;
}
}
}
在 localhost:5000/About
上要求範例的 About 頁面,並檢查標頭來檢視結果:
MVC 篩選條件和頁面篩選條件 (IPageFilter)
Razor Pages 會忽略 MVC 動作篩選條件,因為 Razor Pages 使用處理常式方法。 其他類型的 MVC 篩選條件可供您使用:Authorization、Exception、Resource 和 Result。 如需詳細資訊,請參閱篩選條件主題。
頁面篩選條件 (IPageFilter) 是可套用至 Razor Pages 的篩選條件。 如需詳細資訊,請參閱 Razor Pages 的篩選方法。
其他資源
了解如何使用頁面路由和應用程式模型提供者慣例,來控制 Razor Pages 應用程式中的頁面路由、探索與處理。
當您需要設定個別頁面的自訂頁面路由時,請使用本主題稍後所述的 AddPageRoute 慣例來設定路由至頁面。
若要指定頁面路由、新增路由區段或將參數新增至路由,請使用頁面的 @page
指示詞。 如需詳細資訊,請參閱自訂路由。
有無法做為路由區段或參數名稱的保留字。 如需詳細資訊,請參閱路由:保留路由名稱。
檢視或下載範例程式碼 \(英文\) (如何下載)
案例 | 範例會示範 ... |
---|---|
模型慣例 Conventions.Add
|
將路由範本和標頭新增至應用程式的頁面。 |
頁面路由動作慣例
|
將路由範本新增至資料夾中的頁面,以及新增至單一頁面。 |
頁面模型動作慣例
|
將標頭新增至資料夾中的頁面、將標頭新增至單一頁面,以及設定篩選條件 Factory 將標頭新增至應用程式的頁面。 |
Razor Pages 慣例是使用在 Startup.ConfigureServices
中設定 RazorPagesOptions 的 AddRazorPages 多載來設定。 稍後在本主題會說明下列慣例範例:
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages(options =>
{
options.Conventions.Add( ... );
options.Conventions.AddFolderRouteModelConvention(
"/OtherPages", model => { ... });
options.Conventions.AddPageRouteModelConvention(
"/About", model => { ... });
options.Conventions.AddPageRoute(
"/Contact", "TheContactPage/{text?}");
options.Conventions.AddFolderApplicationModelConvention(
"/OtherPages", model => { ... });
options.Conventions.AddPageApplicationModelConvention(
"/About", model => { ... });
options.Conventions.ConfigureFilter(model => { ... });
options.Conventions.ConfigureFilter( ... );
});
}
路由順序
路由會為處理指定 Order (比對路由)。
順序 | 行為 |
---|---|
-1 | 在處理其他路由之前,會先處理此路由。 |
0 | 未指定順序 (預設值)。 未指派 Order (Order = null ) 會將路由 Order 預設為 0 (零) 進行處理。 |
1, 2, … n | 指定路由處理順序。 |
路由處理是由慣例所建立:
- 路由會循序處理 (-1、0、1、2... n)。
- 路由具有相同
Order
時,會先比對最特定的路由,接著再比對較不特定的路由。 - 在具有相同
Order
和相同數目參數的路由符合要求 URL 時,路由會依新增至 PageConventionCollection 的順序進行處理。
如果可能,請避免依賴已建立的路由處理順序。 一般而言,路由會選取具有 URL 比對的正確路由。 如果您必須設定路由 Order
屬性才能正確地傳送路由要求,則應用程式的路由配置可能會造成用戶端混淆,而且難以維護。 尋求簡化應用程式的路由配置。 範例應用程式需要明確的路由處理順序,才能使用單一應用程式來示範數個路由案例。 不過,您應該嘗試避免在生產應用程式中設定路由 Order
的做法。
Razor Pages 路由和 MVC 控制器路由會共用實作。 MVC 主題中有關路由順序的資訊,可在路由傳送至控制器動作:排序屬性路由中取得。
模型慣例
新增 IPageConvention 的委派,以新增會套用至 Razor Pages 的模型慣例。
將路由模型慣例新增至所有頁面
使用 Conventions 來建立和新增 IPageRouteModelConvention 至頁面路由模型建構期間所套用的 IPageConvention 執行個體集合。
範例應用程式將 {globalTemplate?}
路由範本新增至應用程式中的所有頁面:
public class GlobalTemplatePageRouteModelConvention
: IPageRouteModelConvention
{
public void Apply(PageRouteModel model)
{
var selectorCount = model.Selectors.Count;
for (var i = 0; i < selectorCount; i++)
{
var selector = model.Selectors[i];
model.Selectors.Add(new SelectorModel
{
AttributeRouteModel = new AttributeRouteModel
{
Order = 1,
Template = AttributeRouteModel.CombineTemplates(
selector.AttributeRouteModel.Template,
"{globalTemplate?}"),
}
});
}
}
}
AttributeRouteModel 的 Order 屬性設定為 1
。 這可確保範例應用程式中的下列路由比對行為:
- 本主題稍後會新增
TheContactPage/{text?}
的路由範本。 連絡人頁面路由的預設順序為null
(Order = 0
),因此會在{globalTemplate?}
路由範本之前比對。 - 本主題稍後會新增
{aboutTemplate?}
路由範本。{aboutTemplate?}
範本會指定Order
為2
。 在/About/RouteDataValue
上要求 About 頁面時,由於設定Order
屬性之故,因此 "RouteDataValue" 會載入至RouteData.Values["globalTemplate"]
(Order = 1
),而不是RouteData.Values["aboutTemplate"]
(Order = 2
)。 - 本主題稍後會新增
{otherPagesTemplate?}
路由範本。{otherPagesTemplate?}
範本會指定Order
為2
。 如果使用路由參數 (例如/OtherPages/Page1/RouteDataValue
) 要求 Pages/OtherPages 資料夾中的任何頁面,則由於已設定Order
屬性,系統會將 "RouteDataValue" 載入到RouteData.Values["globalTemplate"]
(Order = 1
),而不是RouteData.Values["otherPagesTemplate"]
(Order = 2
)。
盡可能不要設定 Order
,這會導致 Order = 0
。 依賴路由來選取正確的路由。
將 Razor Pages 新增至服務集合後,系統會在 Startup.ConfigureServices
中新增 Razor Pages 選項 (例如新增 Conventions)。 如需範例,請參閱範例應用程式。
options.Conventions.Add(new GlobalTemplatePageRouteModelConvention());
在 localhost:5000/About/GlobalRouteValue
上要求範例的 About 頁面,並檢查結果:
將應用程式模型慣例新增至所有頁面
使用 Conventions 來建立和新增 IPageApplicationModelConvention 至頁面應用程式模型建構期間所套用的 IPageConvention 執行個體集合。
為了示範這個慣例和本主題稍後的其他慣例,範例應用程式包含了 AddHeaderAttribute
類別。 類別建構函式接受 name
字串和 values
字串陣列。 在其 OnResultExecuting
方法中使用這些值來設定回應標頭。 完整的類別顯示在本主題稍後的頁面模型動作慣例一節中。
範例應用程式會使用 AddHeaderAttribute
類別,將標頭 GlobalHeader
新增至應用程式中的所有頁面:
public class GlobalHeaderPageApplicationModelConvention
: IPageApplicationModelConvention
{
public void Apply(PageApplicationModel model)
{
model.Filters.Add(new AddHeaderAttribute(
"GlobalHeader", new string[] { "Global Header Value" }));
}
}
Startup.cs
:
options.Conventions.Add(new GlobalHeaderPageApplicationModelConvention());
在 localhost:5000/About
上要求範例的 About 頁面,並檢查標頭來檢視結果:
將處理常式模型慣例新增至所有頁面
使用 Conventions 來建立並新增 IPageHandlerModelConvention 至頁面處理常式模型建構期間所套用的 IPageConvention 執行個體集合。
public class GlobalPageHandlerModelConvention
: IPageHandlerModelConvention
{
public void Apply(PageHandlerModel model)
{
// Access the PageHandlerModel
}
}
Startup.cs
:
options.Conventions.Add(new GlobalPageHandlerModelConvention());
頁面路由動作慣例
衍生自 IPageRouteModelProvider 的預設路由模型提供者會叫用慣例,這些慣例是為了要提供設定頁面路由的擴充點。
資料夾路由模型慣例
使用 AddFolderRouteModelConvention 來建立和新增 IPageRouteModelConvention,針對指定資料夾底下的所有頁面在 PageRouteModel 上叫用動作。
範例應用程式會使用 AddFolderRouteModelConvention,將 {otherPagesTemplate?}
路由範本新增至 OtherPages 資料夾中的頁面:
options.Conventions.AddFolderRouteModelConvention("/OtherPages", model =>
{
var selectorCount = model.Selectors.Count;
for (var i = 0; i < selectorCount; i++)
{
var selector = model.Selectors[i];
model.Selectors.Add(new SelectorModel
{
AttributeRouteModel = new AttributeRouteModel
{
Order = 2,
Template = AttributeRouteModel.CombineTemplates(
selector.AttributeRouteModel.Template,
"{otherPagesTemplate?}"),
}
});
}
});
AttributeRouteModel 的 Order 屬性設定為 2
。 這可確保在提供單一路由值時,{globalTemplate?}
的範本 (稍早在本主題中設定為 1
) 會指定第一個路由資料值位置的優先順序。 如果使用路由參數值 (例如 /OtherPages/Page1/RouteDataValue
) 要求 Pages/OtherPages 資料夾中的某個頁面,則由於已設定 Order
屬性,系統會將 "RouteDataValue" 載入到 RouteData.Values["globalTemplate"]
(Order = 1
),而不是 RouteData.Values["otherPagesTemplate"]
(Order = 2
)。
盡可能不要設定 Order
,這會導致 Order = 0
。 依賴路由來選取正確的路由。
在 localhost:5000/OtherPages/Page1/GlobalRouteValue/OtherPagesRouteValue
上要求範例的 Page1 頁面,並檢查結果:
頁面路由模型慣例
使用 AddPageRouteModelConvention 來建立和新增 IPageRouteModelConvention,針對具有指定名稱的頁面在 PageRouteModel 上叫用動作。
範例應用程式會使用 AddPageRouteModelConvention
,將 {aboutTemplate?}
路由範本新增至 About 頁面:
options.Conventions.AddPageRouteModelConvention("/About", model =>
{
var selectorCount = model.Selectors.Count;
for (var i = 0; i < selectorCount; i++)
{
var selector = model.Selectors[i];
model.Selectors.Add(new SelectorModel
{
AttributeRouteModel = new AttributeRouteModel
{
Order = 2,
Template = AttributeRouteModel.CombineTemplates(
selector.AttributeRouteModel.Template,
"{aboutTemplate?}"),
}
});
}
});
AttributeRouteModel 的 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
上要求範例的 About 頁面,並檢查結果:
使用參數轉換器自訂頁面路由
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.AddRazorPages(options =>
{
options.Conventions.Add(
new PageRouteTransformerConvention(
new SlugifyParameterTransformer()));
});
}
public class SlugifyParameterTransformer : IOutboundParameterTransformer
{
public string TransformOutbound(object value)
{
if (value == null) { return null; }
return Regex.Replace(value.ToString(),
"([a-z])([A-Z])",
"$1-$2",
RegexOptions.CultureInvariant,
TimeSpan.FromMilliseconds(100)).ToLowerInvariant();
}
}
警告
使用 System.Text.RegularExpressions 來處理不受信任的輸入時,請傳遞逾時。 惡意使用者可以提供輸入給 RegularExpressions
,導致拒絕服務 (DoS) 攻擊。 使用 RegularExpressions
傳送逾時的 ASP.NET Core 架構 API。
設定頁面路由
使用 AddPageRoute 以設定路由至指定頁面路徑上的頁面。 頁面的所產生連結會使用您指定的路由。 AddPageRoute
使用 AddPageRouteModelConvention
來建立路由。
範例應用程式會針對 Contact.cshtml
建立通往 /TheContactPage
的路由:
options.Conventions.AddPageRoute("/Contact", "TheContactPage/{text?}");
Contact 頁面也可以透過其預設路由在 /Contact
上連線。
範例應用程式的 Contact 頁面自訂路由允許使用選擇性的 text
路由區段 ({text?}
)。 該頁面也會在其 @page
指示詞中包含這個選擇性區段,以防訪客在其 /Contact
路由上存取頁面:
@page "{text?}"
@model ContactModel
@{
ViewData["Title"] = "Contact";
}
<h1>@ViewData["Title"]</h1>
<h2>@Model.Message</h2>
<address>
One Microsoft Way<br>
Redmond, WA 98052-6399<br>
<abbr title="Phone">P:</abbr>
425.555.0100
</address>
<address>
<strong>Support:</strong> <a href="mailto:Support@example.com">Support@example.com</a><br>
<strong>Marketing:</strong> <a href="mailto:Marketing@example.com">Marketing@example.com</a>
</address>
<p>@Model.RouteDataTextTemplateValue</p>
請注意,呈現頁面中針對 Contact 連結所產生的 URL 會反映更新的路由:
請在其一般路由 /Contact
或自訂路由 /TheContactPage
上瀏覽 Contact 頁面。 如果您提供額外的 text
路由區段,該頁面會顯示您提供的 HTML 編碼區段:
頁面模型動作慣例
實作 IPageApplicationModelProvider 的預設頁面模型提供者會叫用慣例,這些慣例是為了要提供設定頁面模型的擴充點。 在建置和修改頁面探索與處理案例時,這些慣例很有用。
對於本節中的範例,範例應用程式會使用 AddHeaderAttribute
類別,這是可套用回應標頭的 ResultFilterAttribute:
public class AddHeaderAttribute : ResultFilterAttribute
{
private readonly string _name;
private readonly string[] _values;
public AddHeaderAttribute(string name, string[] values)
{
_name = name;
_values = values;
}
public override void OnResultExecuting(ResultExecutingContext context)
{
context.HttpContext.Response.Headers.Add(_name, _values);
base.OnResultExecuting(context);
}
}
透過慣例,此範例示範如何將屬性套用至資料夾中的所有頁面,以及套用至單一頁面。
資料夾應用程式模型慣例
使用 AddFolderApplicationModelConvention 來建立和新增 IPageApplicationModelConvention,在指定資料夾底下所有頁面的 PageApplicationModel 執行個體上叫用動作。
此範例示範如何將標頭 OtherPagesHeader
新增至應用程式的 OtherPages 資料夾內的頁面來使用 AddFolderApplicationModelConvention
:
options.Conventions.AddFolderApplicationModelConvention("/OtherPages", model =>
{
model.Filters.Add(new AddHeaderAttribute(
"OtherPagesHeader", new string[] { "OtherPages Header Value" }));
});
在 localhost:5000/OtherPages/Page1
上要求範例的 Page1 頁面,並檢查標頭來檢視結果:
頁面應用程式模型慣例
使用 AddPageApplicationModelConvention 來建立和新增 IPageApplicationModelConvention,針對具有指定名稱的頁面在 PageApplicationModel 上叫用動作。
此範例示範如何將標頭 AboutHeader
新增至 About 頁面來使用 AddPageApplicationModelConvention
:
options.Conventions.AddPageApplicationModelConvention("/About", model =>
{
model.Filters.Add(new AddHeaderAttribute(
"AboutHeader", new string[] { "About Header Value" }));
});
在 localhost:5000/About
上要求範例的 About 頁面,並檢查標頭來檢視結果:
設定篩選條件
ConfigureFilter 會設定要套用的指定篩選條件。 您可以實作篩選條件類別,但範例應用程式是示範如何在 Lambda 運算式中實作篩選條件,該運算式會在幕後實作為 Factory 以傳回篩選條件:
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 頁面,並檢查標頭來檢視結果:
設定篩選條件 Factory
ConfigureFilter 會設定指定的 Factory,以將篩選條件套用至所有 Razor 頁面。
範例應用程式示範如何以應用程式頁面的兩個值新增標頭 FilterFactoryHeader
來使用篩選條件 Factory:
options.Conventions.ConfigureFilter(new AddHeaderWithFactory());
AddHeaderWithFactory.cs
:
public class AddHeaderWithFactory : IFilterFactory
{
// Implement IFilterFactory
public IFilterMetadata CreateInstance(IServiceProvider serviceProvider)
{
return new AddHeaderFilter();
}
private class AddHeaderFilter : IResultFilter
{
public void OnResultExecuting(ResultExecutingContext context)
{
context.HttpContext.Response.Headers.Add(
"FilterFactoryHeader",
new string[]
{
"Filter Factory Header Value 1",
"Filter Factory Header Value 2"
});
}
public void OnResultExecuted(ResultExecutedContext context)
{
}
}
public bool IsReusable
{
get
{
return false;
}
}
}
在 localhost:5000/About
上要求範例的 About 頁面,並檢查標頭來檢視結果:
MVC 篩選條件和頁面篩選條件 (IPageFilter)
Razor Pages 會忽略 MVC 動作篩選條件,因為 Razor Pages 使用處理常式方法。 其他類型的 MVC 篩選條件可供您使用:Authorization、Exception、Resource 和 Result。 如需詳細資訊,請參閱篩選條件主題。
頁面篩選條件 (IPageFilter) 是可套用至 Razor Pages 的篩選條件。 如需詳細資訊,請參閱 Razor Pages 的篩選方法。
其他資源
了解如何使用頁面路由和應用程式模型提供者慣例,來控制 Razor Pages 應用程式中的頁面路由、探索與處理。
當您需要設定個別頁面的自訂頁面路由時,請使用本主題稍後所述的 AddPageRoute 慣例來設定路由至頁面。
若要指定頁面路由、新增路由區段或將參數新增至路由,請使用頁面的 @page
指示詞。 如需詳細資訊,請參閱自訂路由。
有無法做為路由區段或參數名稱的保留字。 如需詳細資訊,請參閱路由:保留路由名稱。
檢視或下載範例程式碼 \(英文\) (如何下載)
案例 | 範例會示範 ... |
---|---|
模型慣例 Conventions.Add
|
將路由範本和標頭新增至應用程式的頁面。 |
頁面路由動作慣例
|
將路由範本新增至資料夾中的頁面,以及新增至單一頁面。 |
頁面模型動作慣例
|
將標頭新增至資料夾中的頁面、將標頭新增至單一頁面,以及設定篩選條件 Factory 將標頭新增至應用程式的頁面。 |
Razor Pages 慣例是 Startup
類別的服務集合上 AddMvc 的 AddRazorPagesOptions 擴充方法來進行新增和設定。 稍後在本主題會說明下列慣例範例:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc()
.AddRazorPagesOptions(options =>
{
options.Conventions.Add( ... );
options.Conventions.AddFolderRouteModelConvention(
"/OtherPages", model => { ... });
options.Conventions.AddPageRouteModelConvention(
"/About", model => { ... });
options.Conventions.AddPageRoute(
"/Contact", "TheContactPage/{text?}");
options.Conventions.AddFolderApplicationModelConvention(
"/OtherPages", model => { ... });
options.Conventions.AddPageApplicationModelConvention(
"/About", model => { ... });
options.Conventions.ConfigureFilter(model => { ... });
options.Conventions.ConfigureFilter( ... );
});
}
路由順序
路由會為處理指定 Order (比對路由)。
順序 | 行為 |
---|---|
-1 | 在處理其他路由之前,會先處理此路由。 |
0 | 未指定順序 (預設值)。 未指派 Order (Order = null ) 會將路由 Order 預設為 0 (零) 進行處理。 |
1, 2, … n | 指定路由處理順序。 |
路由處理是由慣例所建立:
- 路由會循序處理 (-1、0、1、2... n)。
- 路由具有相同
Order
時,會先比對最特定的路由,接著再比對較不特定的路由。 - 在具有相同
Order
和相同數目參數的路由符合要求 URL 時,路由會依新增至 PageConventionCollection 的順序進行處理。
如果可能,請避免依賴已建立的路由處理順序。 一般而言,路由會選取具有 URL 比對的正確路由。 如果您必須設定路由 Order
屬性才能正確地傳送路由要求,則應用程式的路由配置可能會造成用戶端混淆,而且難以維護。 尋求簡化應用程式的路由配置。 範例應用程式需要明確的路由處理順序,才能使用單一應用程式來示範數個路由案例。 不過,您應該嘗試避免在生產應用程式中設定路由 Order
的做法。
Razor Pages 路由和 MVC 控制器路由會共用實作。 MVC 主題中有關路由順序的資訊,可在路由傳送至控制器動作:排序屬性路由中取得。
模型慣例
新增 IPageConvention 的委派,以新增會套用至 Razor Pages 的模型慣例。
將路由模型慣例新增至所有頁面
使用 Conventions 來建立和新增 IPageRouteModelConvention 至頁面路由模型建構期間所套用的 IPageConvention 執行個體集合。
範例應用程式將 {globalTemplate?}
路由範本新增至應用程式中的所有頁面:
public class GlobalTemplatePageRouteModelConvention
: IPageRouteModelConvention
{
public void Apply(PageRouteModel model)
{
var selectorCount = model.Selectors.Count;
for (var i = 0; i < selectorCount; i++)
{
var selector = model.Selectors[i];
model.Selectors.Add(new SelectorModel
{
AttributeRouteModel = new AttributeRouteModel
{
Order = 1,
Template = AttributeRouteModel.CombineTemplates(
selector.AttributeRouteModel.Template,
"{globalTemplate?}"),
}
});
}
}
}
AttributeRouteModel 的 Order 屬性設定為 1
。 這可確保範例應用程式中的下列路由比對行為:
- 本主題稍後會新增
TheContactPage/{text?}
的路由範本。 連絡人頁面路由的預設順序為null
(Order = 0
),因此會在{globalTemplate?}
路由範本之前比對。 - 本主題稍後會新增
{aboutTemplate?}
路由範本。{aboutTemplate?}
範本會指定Order
為2
。 在/About/RouteDataValue
上要求 About 頁面時,由於設定Order
屬性之故,因此 "RouteDataValue" 會載入至RouteData.Values["globalTemplate"]
(Order = 1
),而不是RouteData.Values["aboutTemplate"]
(Order = 2
)。 - 本主題稍後會新增
{otherPagesTemplate?}
路由範本。{otherPagesTemplate?}
範本會指定Order
為2
。 如果使用路由參數 (例如/OtherPages/Page1/RouteDataValue
) 要求 Pages/OtherPages 資料夾中的任何頁面,則由於已設定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
上要求範例的 About 頁面,並檢查結果:
將應用程式模型慣例新增至所有頁面
使用 Conventions 來建立和新增 IPageApplicationModelConvention 至頁面應用程式模型建構期間所套用的 IPageConvention 執行個體集合。
為了示範這個慣例和本主題稍後的其他慣例,範例應用程式包含了 AddHeaderAttribute
類別。 類別建構函式接受 name
字串和 values
字串陣列。 在其 OnResultExecuting
方法中使用這些值來設定回應標頭。 完整的類別顯示在本主題稍後的頁面模型動作慣例一節中。
範例應用程式會使用 AddHeaderAttribute
類別,將標頭 GlobalHeader
新增至應用程式中的所有頁面:
public class GlobalHeaderPageApplicationModelConvention
: IPageApplicationModelConvention
{
public void Apply(PageApplicationModel model)
{
model.Filters.Add(new AddHeaderAttribute(
"GlobalHeader", new string[] { "Global Header Value" }));
}
}
Startup.cs
:
options.Conventions.Add(new GlobalHeaderPageApplicationModelConvention());
在 localhost:5000/About
上要求範例的 About 頁面,並檢查標頭來檢視結果:
將處理常式模型慣例新增至所有頁面
使用 Conventions 來建立並新增 IPageHandlerModelConvention 至頁面處理常式模型建構期間所套用的 IPageConvention 執行個體集合。
public class GlobalPageHandlerModelConvention
: IPageHandlerModelConvention
{
public void Apply(PageHandlerModel model)
{
// Access the PageHandlerModel
}
}
Startup.cs
:
options.Conventions.Add(new GlobalPageHandlerModelConvention());
頁面路由動作慣例
衍生自 IPageRouteModelProvider 的預設路由模型提供者會叫用慣例,這些慣例是為了要提供設定頁面路由的擴充點。
資料夾路由模型慣例
使用 AddFolderRouteModelConvention 來建立和新增 IPageRouteModelConvention,針對指定資料夾底下的所有頁面在 PageRouteModel 上叫用動作。
範例應用程式會使用 AddFolderRouteModelConvention,將 {otherPagesTemplate?}
路由範本新增至 OtherPages 資料夾中的頁面:
options.Conventions.AddFolderRouteModelConvention("/OtherPages", model =>
{
var selectorCount = model.Selectors.Count;
for (var i = 0; i < selectorCount; i++)
{
var selector = model.Selectors[i];
model.Selectors.Add(new SelectorModel
{
AttributeRouteModel = new AttributeRouteModel
{
Order = 2,
Template = AttributeRouteModel.CombineTemplates(
selector.AttributeRouteModel.Template,
"{otherPagesTemplate?}"),
}
});
}
});
AttributeRouteModel 的 Order 屬性設定為 2
。 這可確保在提供單一路由值時,{globalTemplate?}
的範本 (稍早在本主題中設定為 1
) 會指定第一個路由資料值位置的優先順序。 如果使用路由參數值 (例如 /OtherPages/Page1/RouteDataValue
) 要求 Pages/OtherPages 資料夾中的某個頁面,則由於已設定 Order
屬性,系統會將 "RouteDataValue" 載入到 RouteData.Values["globalTemplate"]
(Order = 1
),而不是 RouteData.Values["otherPagesTemplate"]
(Order = 2
)。
盡可能不要設定 Order
,這會導致 Order = 0
。 依賴路由來選取正確的路由。
在 localhost:5000/OtherPages/Page1/GlobalRouteValue/OtherPagesRouteValue
上要求範例的 Page1 頁面,並檢查結果:
頁面路由模型慣例
使用 AddPageRouteModelConvention 來建立和新增 IPageRouteModelConvention,針對具有指定名稱的頁面在 PageRouteModel 上叫用動作。
範例應用程式會使用 AddPageRouteModelConvention
,將 {aboutTemplate?}
路由範本新增至 About 頁面:
options.Conventions.AddPageRouteModelConvention("/About", model =>
{
var selectorCount = model.Selectors.Count;
for (var i = 0; i < selectorCount; i++)
{
var selector = model.Selectors[i];
model.Selectors.Add(new SelectorModel
{
AttributeRouteModel = new AttributeRouteModel
{
Order = 2,
Template = AttributeRouteModel.CombineTemplates(
selector.AttributeRouteModel.Template,
"{aboutTemplate?}"),
}
});
}
});
AttributeRouteModel 的 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
上要求範例的 About 頁面,並檢查結果:
設定頁面路由
使用 AddPageRoute 以設定路由至指定頁面路徑上的頁面。 頁面的所產生連結會使用您指定的路由。 AddPageRoute
使用 AddPageRouteModelConvention
來建立路由。
範例應用程式會針對 Contact.cshtml
建立通往 /TheContactPage
的路由:
options.Conventions.AddPageRoute("/Contact", "TheContactPage/{text?}");
Contact 頁面也可以透過其預設路由在 /Contact
上連線。
範例應用程式的 Contact 頁面自訂路由允許使用選擇性的 text
路由區段 ({text?}
)。 該頁面也會在其 @page
指示詞中包含這個選擇性區段,以防訪客在其 /Contact
路由上存取頁面:
@page "{text?}"
@model ContactModel
@{
ViewData["Title"] = "Contact";
}
<h1>@ViewData["Title"]</h1>
<h2>@Model.Message</h2>
<address>
One Microsoft Way<br>
Redmond, WA 98052-6399<br>
<abbr title="Phone">P:</abbr>
425.555.0100
</address>
<address>
<strong>Support:</strong> <a href="mailto:Support@example.com">Support@example.com</a><br>
<strong>Marketing:</strong> <a href="mailto:Marketing@example.com">Marketing@example.com</a>
</address>
<p>@Model.RouteDataTextTemplateValue</p>
請注意,呈現頁面中針對 Contact 連結所產生的 URL 會反映更新的路由:
請在其一般路由 /Contact
或自訂路由 /TheContactPage
上瀏覽 Contact 頁面。 如果您提供額外的 text
路由區段,該頁面會顯示您提供的 HTML 編碼區段:
頁面模型動作慣例
實作 IPageApplicationModelProvider 的預設頁面模型提供者會叫用慣例,這些慣例是為了要提供設定頁面模型的擴充點。 在建置和修改頁面探索與處理案例時,這些慣例很有用。
對於本節中的範例,範例應用程式會使用 AddHeaderAttribute
類別,這是可套用回應標頭的 ResultFilterAttribute:
public class AddHeaderAttribute : ResultFilterAttribute
{
private readonly string _name;
private readonly string[] _values;
public AddHeaderAttribute(string name, string[] values)
{
_name = name;
_values = values;
}
public override void OnResultExecuting(ResultExecutingContext context)
{
context.HttpContext.Response.Headers.Add(_name, _values);
base.OnResultExecuting(context);
}
}
透過慣例,此範例示範如何將屬性套用至資料夾中的所有頁面,以及套用至單一頁面。
資料夾應用程式模型慣例
使用 AddFolderApplicationModelConvention 來建立和新增 IPageApplicationModelConvention,在指定資料夾底下所有頁面的 PageApplicationModel 執行個體上叫用動作。
此範例示範如何將標頭 OtherPagesHeader
新增至應用程式的 OtherPages 資料夾內的頁面來使用 AddFolderApplicationModelConvention
:
options.Conventions.AddFolderApplicationModelConvention("/OtherPages", model =>
{
model.Filters.Add(new AddHeaderAttribute(
"OtherPagesHeader", new string[] { "OtherPages Header Value" }));
});
在 localhost:5000/OtherPages/Page1
上要求範例的 Page1 頁面,並檢查標頭來檢視結果:
頁面應用程式模型慣例
使用 AddPageApplicationModelConvention 來建立和新增 IPageApplicationModelConvention,針對具有指定名稱的頁面在 PageApplicationModel 上叫用動作。
此範例示範如何將標頭 AboutHeader
新增至 About 頁面來使用 AddPageApplicationModelConvention
:
options.Conventions.AddPageApplicationModelConvention("/About", model =>
{
model.Filters.Add(new AddHeaderAttribute(
"AboutHeader", new string[] { "About Header Value" }));
});
在 localhost:5000/About
上要求範例的 About 頁面,並檢查標頭來檢視結果:
設定篩選條件
ConfigureFilter 會設定要套用的指定篩選條件。 您可以實作篩選條件類別,但範例應用程式是示範如何在 Lambda 運算式中實作篩選條件,該運算式會在幕後實作為 Factory 以傳回篩選條件:
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 頁面,並檢查標頭來檢視結果:
設定篩選條件 Factory
ConfigureFilter 會設定指定的 Factory,以將篩選條件套用至所有 Razor 頁面。
範例應用程式示範如何以應用程式頁面的兩個值新增標頭 FilterFactoryHeader
來使用篩選條件 Factory:
options.Conventions.ConfigureFilter(new AddHeaderWithFactory());
AddHeaderWithFactory.cs
:
public class AddHeaderWithFactory : IFilterFactory
{
// Implement IFilterFactory
public IFilterMetadata CreateInstance(IServiceProvider serviceProvider)
{
return new AddHeaderFilter();
}
private class AddHeaderFilter : IResultFilter
{
public void OnResultExecuting(ResultExecutingContext context)
{
context.HttpContext.Response.Headers.Add(
"FilterFactoryHeader",
new string[]
{
"Filter Factory Header Value 1",
"Filter Factory Header Value 2"
});
}
public void OnResultExecuted(ResultExecutedContext context)
{
}
}
public bool IsReusable
{
get
{
return false;
}
}
}
在 localhost:5000/About
上要求範例的 About 頁面,並檢查標頭來檢視結果:
MVC 篩選條件和頁面篩選條件 (IPageFilter)
Razor Pages 會忽略 MVC 動作篩選條件,因為 Razor Pages 使用處理常式方法。 其他類型的 MVC 篩選條件可供您使用:Authorization、Exception、Resource 和 Result。 如需詳細資訊,請參閱篩選條件主題。
頁面篩選條件 (IPageFilter) 是可套用至 Razor Pages 的篩選條件。 如需詳細資訊,請參閱 Razor Pages 的篩選方法。